Slide 1

Slide 1 text

Remix💿でWeb標準を学んだ1年間 フロントエンドの技術選定 〜2023を振り返る〜 Lunch LT Yukiya Nakagawa a.k.a Nkzn 0:00

Slide 2

Slide 2 text

We are hiring! ● ソフトウェアエンジニアを積極採用中です! ● カジュアル面談お待ちしてます →   @NkznにDMください ● 求人情報はこちら Findy HRMOS monicle.co.jp

Slide 3

Slide 3 text

自己紹介 ● 中川幸哉 a.k.a Nkzn(なかざん) ● ‘86世代🐰の36歳(来月37になります) ● 新潟生まれ新潟育ち ● 8歳と4歳の父で妻の夫 ● 2011〜2021年は農業IT🌾の人 ● 2021年から株式会社モニクル ○ 資産運用お手伝いサービス「マネイロ」のIT裏方 0:05

Slide 4

Slide 4 text

https://speakerdeck.com/monicle/culture-deck 0:20

Slide 5

Slide 5 text

どんなプロダクトに Remix💿を採用したのか 0:35

Slide 6

Slide 6 text

https://speakerdeck.com/monicle/culture-deck 前月の収益を 毎月上旬に 自動で集計したい! 0:50

Slide 7

Slide 7 text

どんなプロダクトに採用したのか ● 社内向けの収益計算システム(会計システムのサブシステム) ● フロントエンド用のフレームワークとして採用 ○ DB操作やお金の計算はバックエンドサーバーに任せる ● APIキャッシュはいらない ○ 少数の社員しか触らない&管理システムとしての側面が強い ○ 常に最新の情報がAPIサーバーから出てきて表示できればよい ● 権限管理は結構重めで、監査法人が目を光らせている ○ 上場のために作ってるシステムなので仕方ないね 1:05

Slide 8

Slide 8 text

なぜRemix💿を採用したのか 1:20

Slide 9

Slide 9 text

選定時期 ● 2022年夏〜秋ごろ ● Remixはv1.7.1くらい ● Why NOT App Router ○ Next.js v13.0は2022年10月末リリースでした ○ 物理的に選択肢に上らない時期だった 1:35

Slide 10

Slide 10 text

開発メンバーの想定スキル ● メイン事業のひとつ https://moneiro.jp はNext.js製 ○ 開発組織全体としては基本的にNext.jsを選びがち ○ Pages Routerの世界観には慣れている人が多い ○ 新規開発ではApp Routerも採用はしている ● TypeScriptとReactは書ける ● File-system based routerも馴染み深い ● Next.js経由でレイアウト的な考え方も知ってた へっだー さいどばー ここだけ 画面遷移する レイアウト的なやつ 1:50

Slide 11

Slide 11 text

プロダクトの要件・特性 ● 社内のSFA内にある契約データを収益データにコンバートするやつ ● ユーザー数は数名 ● ビジネスロジックやデータベース操作はバックエンドサーバーに任 せて、別のクライアントと繋ぐ余地を残したい ● フロントエンドのフレームワークはなんでもいいといえばなんでも いい ● 強いて言えば、常に最新の情報を表示したいので、キャッシュ機構 はあってもあんまり使わない 2:05

Slide 12

Slide 12 text

Remix💿にした要因 ● Next.jsへの逆張り ● 通信と画面遷移が統合されたフ レームワーク ● 学習コストを効率的に使えそう ○ Web標準のパーツをフレーム ワークに組み込んでいる ● スイッチングコストを減らせそう ○ サーバーサイドのコードもブ ラウザっぽく書ける ● フレームワークとしてはキャッ シュ機構がなく、HTTP Headerを 扱いやすくすることで対応してい る ● React Routerベース ○ ちょくちょく使ってきたので 土地勘がある ○ 割としんどいBreaking Changeやりがち問題 2:20

Slide 13

Slide 13 text

v1のPhilosophyに惚れてしまった ● https://remix.run/docs/en/1.19.3/pages/philosophy ● Web標準には結構いいパーツが揃ってきているので活用することに したし、フレームワークによる隠蔽・抽象化も最小限にする ○ ex. 通信周りはlib.dom.d.tsの型定義をそのまま使うことが多い ● せっかく学習コストを払うならWeb標準を学んだほうが潰しが効く – Get good at Remix, get good at the web. v2にはエモ文書置き場がないのでなくなっちゃった 😢 2:35

Slide 14

Slide 14 text

3分でわかるRemix  開発 2:50

Slide 15

Slide 15 text

export async function loader() { // データ読み込み( GraphQL Query) } export default function Component() { const loaderData = useLoaderData(); const actionData = useActionData(); // このルートに表示したい UIを定義する } export async function action() { // データを更新する( GraphQL Mutation) } Route app/routes/ 内の1ファイル 3:05

Slide 16

Slide 16 text

export async function loader({ request, // Fetch APIのRequest params, }: LoaderFunctionArgs) { const { id } = params; const user = await getUser(request, id); // Fetch APIのResponse return new Response(JSON.stringify({ displayName: user.displayName, email: user.email, }), { headers: { "Content-Type": "application/json; charset=utf-8", }, }); } Loader データ取得関数 このroute用GET専門エンド ポイントみたいなイメージ 3:20

Slide 17

Slide 17 text

export async function loader({ request, // Fetch APIのRequest params, }: LoaderFunctionArgs) { const { id } = params; const user = await getUser(request, id); return json({ displayName: user.displayName, email: user.email, }); } Loader Responseの薄いラッパー `json()` 3:35

Slide 18

Slide 18 text

Action export async function action({ request, }: ActionFunctionArgs) { // Requestオブジェクトからフォームデータを取得する const body = await request.formData(); const name = body.get("visitorsName"); return json({ message: `Hello, ${name}` }); } export default function Component() { const data = useActionData(); return ( {data ? data.message : "Waiting..."} ); } loaderと同じインター フェース フォームリクエスト受付専 用関数 3:50

Slide 19

Slide 19 text

Fullstack Data Flow https://remix.run/docs/en/2.5.1/discussion/data-flow 4:05

Slide 20

Slide 20 text

File-system based routing app/ ├── routes/ │ ├── _index.tsx │ ├── about.tsx │ ├── concerts._index.tsx │ ├── concerts.$city.tsx │ ├── concerts.trending.tsx │ └── concerts.tsx └── root.tsx Next.jsと大体一緒! と言いたかったけど、v2で ドット区切りになりました /concerts/* のレイアウト /concerts /concerts/$city /concerts/trending / /about 4:20

Slide 21

Slide 21 text

認証はremix-authでなんとかしてる ● Remixにはセッション情報管理の仕組みが標準で組み込まれている ○ https://remix.run/docs/en/main/utils/sessions ○ まずはCookieに保存して、4KB制限を超えそうになったらKVSに移行すると かでもいいかも ● 認証フローの管理が得意なremix-authを併用すると便利 ○ https://github.com/sergiodxa/remix-auth ● 社内標準のIdPがMicrosoft Entra ID(旧Azure AD)なので、 remix-auth-oauth2をベースにOAuth2の認証フローを組んである ○ https://github.com/sergiodxa/remix-auth-oauth2 ○ (参考)https://github.com/juhanakristian/remix-auth-microsoft 4:35

Slide 22

Slide 22 text

Remix💿を学んで Web標準(というかHTML) に再入門した事例 4:50

Slide 23

Slide 23 text

テーブルで1行1フォームを作りたい 5:05

Slide 24

Slide 24 text

私たちのフォーム周り事情 in Remix💿 ● 基本は古き良き `` で、実際にはSPA的な動作をサポートするため に薄くラップした `` を使う ● フォーム管理にはremix-validated-formを使っている ○ https://www.remix-validated-form.io/ ○ Zodで書いたスキーマをバリデーションに利用するためのアダプ ター ● 非制御コンポーネント縛りで頑張ることにしている ○ JavaScriptのロードが完了する前からユーザーが触れたほうが Remixっぽい 5:20

Slide 25

Slide 25 text

the 愚直 2023-11-23 tr > form > td > input 5:35

Slide 26

Slide 26 text

InvalidなHTMLとしてバチクソ怒られた (それはそう) 5:50

Slide 27

Slide 27 text

HTMLど素人ワイ、StackOverflowで救いを得る https://stackoverflow.com/questions/1249688/html-is-it-possible-to-have-a-form-tag-in-each-table-row-in-a-xhtml-valid-way 6:05

Slide 28

Slide 28 text

form属性を使う 2023-11-23 tr > td > form#form1 > input[form=”form1”] tdの中にある分には valid扱い form要素のid属性に指定した値を input要素のform属性に指定すると form要素の外側にある input要素も紐付けられる 6:20

Slide 29

Slide 29 text

We got Kotonaki. 6:35

Slide 30

Slide 30 text

改めて見てみる https://stackoverflow.com/questions/1249688/html-is-it-possible-to-have-a-form-tag-in-each-table-row-in-a-xhtml-valid-way 6:50

Slide 31

Slide 31 text

HTMLど素人ワイ、 15年前(2009)に質問されて 10年前(2014)に回答された StackOverflowに救われる 7:05

Slide 32

Slide 32 text

恥の多い人生を送ってきました ● どこかWeb標準を軽視していた自分に気付かされる機会が増えた ● Remixで開発していると、Web標準を学ぶ機会が多く得られる ● MDNを参照する頻度が増えるごとに、RemixやReactが死んでも使 えるスキルが手元に残る ● ありがとうRemix、ありがとうWeb標準、これからもよろしく 7:20

Slide 33

Slide 33 text

1年間やってきて ● 通信周りの非同期処理について頭を悩ませる頻度が激減した ● よりプロダクトが事業に与えるバリューについて考える時間が増え た ● 昔よりもMDNと仲良くなった気がする ● Remixは愚直で退屈なフレームワークなのかもしれない ● 僕はフレームワークよりプロダクト、プロダクトより事業そのもの にエキサイトしたいので、フレームワークは退屈でもいい ● Remix、一度お試しください 7:35

Slide 34

Slide 34 text

おまけ Remix💿のバージョンアップ事情 (時間がなければ割愛します) 7:50

Slide 35

Slide 35 text

React Router被害者の会 ● RemixのコアライブラリでもあるReact Routerは、アップグレード 体制がちょっと悪名高かった ● 特にv3→v4でごっそり変わって、結局追従できなかったという人も https://twitter.com/mizchi/status/856797318930026497 8:05

Slide 36

Slide 36 text

Remixでどうなったの ● 2023年9月にv2が出たので振り返ってみる ○ https://remix.run/blog/remix-v2 ● 大きめのBreaking Changeはあったがフォローが手厚かった印象 8:20

Slide 37

Slide 37 text

内容自体は大小色々あった ● アップグレードガイドを見てもらうとわかるけど、変更自体はめ ちゃくちゃあった ○ https://remix.run/docs/en/2.5.1/start/v2 ● これをビッグバンリリースしていたら、たぶんみんなブチ切れてい たと思う ● 実際にはそうならないための手厚い配慮が行われた 8:35

Slide 38

Slide 38 text

Remix💿 future flag /** @type {import('@remix-run/dev').AppConfig} */ module.exports = { future: { v2_meta: true, // since 2022.12 v2_errorBoundary: true, // since 2023.04 v2_normalizeFormMethod: true, // since 2023.04 v2_routeConvention: false, // since 2023.04 v2_headers: true, // since 2023.06 v2_dev: false, // since 2023.06 }, }; v1 → v2 8:50

Slide 39

Slide 39 text

future flagの導入 ● Vueのv2→v3のアップグレードの際のfeature flagの使い方にインスパイアされ た、future flagというものを用いて、穏便にアップグレードを進める作戦が採ら れた ○ https://remix.run/blog/future-flags ● v1.xの内に内部的にv2版のモジュールがオプトインでリリースされており、 remix.config.jsでフラグを切り替えることで、特定の機能のみをv2版で動作させ ることができた ● 一つ一つのアップグレードについては、全くトラブルがなかったとは言えないも のの、重たいものについてはv2のstableリリースまで、約半年の対応期間が与え られたことになる 9:05

Slide 40

Slide 40 text

Shopify買収の影響かも ● メジャーバージョンもう1回分くらいは注視してもいいかもしれな いけど、ひとまず今回は慎重だったように見えた ● 2022年10月にShopifyに買収されたのが良い影響になったのかも ○ https://remix.run/blog/remixing-shopify ● ShopifyのECサイト自作用SDK、HydrogenがRemixベースになった ● あんまりにも非互換なアップグレードをしてしまうと、普通に ShopifyのB2B事業の顧客に迷惑がかかるので、迂闊にビッグバンリ リースできなくなったのでは 9:20

Slide 41

Slide 41 text

Shopifyは堅実に進めていくイメージ ● 以前、Shopifyアプリの内部実装を徐々にReact Nativeに置き換え ていくプロジェクトがあったりした ○ https://shopify.engineering/migrating-our-largest-mobile- app-to-react-native ● 顧客へ悪影響が出やすいビッグバンリリースは避け、たとえ技術的 に困難な道になろうと漸進的に進めていく文化があるように感じた ● Remixもそんな感じで進めていってほしい(期待) 9:35

Slide 42

Slide 42 text

完 9:50

Slide 43

Slide 43 text

We are hiring! ● ソフトウェアエンジニアを積極採用中です! ● カジュアル面談お待ちしてます →   @NkznにDMください ● 求人情報はこちら Findy HRMOS monicle.co.jp 10:00