Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RemixでWeb標準を学んだ1年間 / First year with Remix
Search
Yukiya Nakagawa
January 23, 2024
Technology
23
8.3k
RemixでWeb標準を学んだ1年間 / First year with Remix
フロントエンドの技術選定 ~2023を振り返る~ Lunch LT での発表資料です
https://findy.connpass.com/event/306714/
Yukiya Nakagawa
January 23, 2024
Tweet
Share
More Decks by Yukiya Nakagawa
See All by Yukiya Nakagawa
Remix × Cloudflare Pages × Sentry 奮闘記 / remix-pages-sentry
nkzn
1
1.1k
Cloudflareスタックで月間1200万UUの経済メディアにアバター画像生成サービスを作る / Cloudflare Developer Platform for AI avatar service
nkzn
7
3k
5分で流し読むCloudflare Developer Platform
nkzn
3
310
次世代Web認証「パスキー」 / mo-zatsudan-passkey
nkzn
31
18k
パスキーについて今日時点の僕が知っていること / What I Know About Passkeys as of Today
nkzn
8
2.8k
青い空の歩き方 / Flying in the bluesky
nkzn
1
290
SPAの歴史とRemix SPAモードという到達点 / the SPA's chronicle reaches to remix
nkzn
48
17k
純粋培養フルリモート開発組織のワーク&ライフスタイル / monicle full remote style
nkzn
5
4k
資産運用を対面で相談するサービスでITエンジニアがやることあるの? / derta-gig-04
nkzn
0
1.4k
Other Decks in Technology
See All in Technology
表現を育てる
kiyou77
1
210
スタートアップ1人目QAエンジニアが QAチームを立ち上げ、“個”からチーム、 そして“組織”に成長するまで / How to set up QA team at reiwatravel
mii3king
2
1.4k
ハッキングの世界に迫る~攻撃者の思考で考えるセキュリティ~
nomizone
13
5.1k
アジャイル開発とスクラム
araihara
0
170
Developers Summit 2025 浅野卓也(13-B-7 LegalOn Technologies)
legalontechnologies
PRO
0
650
10分で紹介するAmazon Bedrock利用時のセキュリティ対策 / 10-minutes introduction to security measures when using Amazon Bedrock
hideakiaoyagi
0
180
Datadogとともにオブザーバビリティを布教しよう
mego2221
0
140
飲食店予約台帳を支えるインタラクティブ UI 設計と実装
siropaca
7
1.7k
リアルタイム分析データベースで実現する SQLベースのオブザーバビリティ
mikimatsumoto
0
1.3k
一度 Expo の採用を断念したけど、 再度 Expo の導入を検討している話
ichiki1023
1
160
Amazon S3 Tablesと外部分析基盤連携について / Amazon S3 Tables and External Data Analytics Platform
nttcom
0
130
Developer Summit 2025 [14-D-1] Yuki Hattori
yuhattor
19
6.1k
Featured
See All Featured
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
630
The Cost Of JavaScript in 2023
addyosmani
47
7.3k
Adopting Sorbet at Scale
ufuk
74
9.2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
4 Signs Your Business is Dying
shpigford
182
22k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
27
1.9k
It's Worth the Effort
3n
184
28k
A Tale of Four Properties
chriscoyier
158
23k
Rebuilding a faster, lazier Slack
samanthasiow
80
8.8k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Agile that works and the tools we love
rasmusluckow
328
21k
How to Ace a Technical Interview
jacobian
276
23k
Transcript
Remix💿でWeb標準を学んだ1年間 フロントエンドの技術選定 〜2023を振り返る〜 Lunch LT Yukiya Nakagawa a.k.a Nkzn 0:00
We are hiring! • ソフトウェアエンジニアを積極採用中です! • カジュアル面談お待ちしてます → @NkznにDMください •
求人情報はこちら Findy HRMOS monicle.co.jp
自己紹介 • 中川幸哉 a.k.a Nkzn(なかざん) • ‘86世代🐰の36歳(来月37になります) • 新潟生まれ新潟育ち •
8歳と4歳の父で妻の夫 • 2011〜2021年は農業IT🌾の人 • 2021年から株式会社モニクル ◦ 資産運用お手伝いサービス「マネイロ」のIT裏方 0:05
https://speakerdeck.com/monicle/culture-deck 0:20
どんなプロダクトに Remix💿を採用したのか 0:35
https://speakerdeck.com/monicle/culture-deck 前月の収益を 毎月上旬に 自動で集計したい! 0:50
どんなプロダクトに採用したのか • 社内向けの収益計算システム(会計システムのサブシステム) • フロントエンド用のフレームワークとして採用 ◦ DB操作やお金の計算はバックエンドサーバーに任せる • APIキャッシュはいらない ◦
少数の社員しか触らない&管理システムとしての側面が強い ◦ 常に最新の情報がAPIサーバーから出てきて表示できればよい • 権限管理は結構重めで、監査法人が目を光らせている ◦ 上場のために作ってるシステムなので仕方ないね 1:05
なぜRemix💿を採用したのか 1:20
選定時期 • 2022年夏〜秋ごろ • Remixはv1.7.1くらい • Why NOT App Router
◦ Next.js v13.0は2022年10月末リリースでした ◦ 物理的に選択肢に上らない時期だった 1:35
開発メンバーの想定スキル • メイン事業のひとつ https://moneiro.jp はNext.js製 ◦ 開発組織全体としては基本的にNext.jsを選びがち ◦ Pages Routerの世界観には慣れている人が多い
◦ 新規開発ではApp Routerも採用はしている • TypeScriptとReactは書ける • File-system based routerも馴染み深い • Next.js経由でレイアウト的な考え方も知ってた へっだー さいどばー ここだけ 画面遷移する レイアウト的なやつ 1:50
プロダクトの要件・特性 • 社内のSFA内にある契約データを収益データにコンバートするやつ • ユーザー数は数名 • ビジネスロジックやデータベース操作はバックエンドサーバーに任 せて、別のクライアントと繋ぐ余地を残したい • フロントエンドのフレームワークはなんでもいいといえばなんでも
いい • 強いて言えば、常に最新の情報を表示したいので、キャッシュ機構 はあってもあんまり使わない 2:05
Remix💿にした要因 • Next.jsへの逆張り • 通信と画面遷移が統合されたフ レームワーク • 学習コストを効率的に使えそう ◦ Web標準のパーツをフレーム
ワークに組み込んでいる • スイッチングコストを減らせそう ◦ サーバーサイドのコードもブ ラウザっぽく書ける • フレームワークとしてはキャッ シュ機構がなく、HTTP Headerを 扱いやすくすることで対応してい る • React Routerベース ◦ ちょくちょく使ってきたので 土地勘がある ◦ 割としんどいBreaking Changeやりがち問題 2:20
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
3分でわかるRemix 開発 2:50
export async function loader() { // データ読み込み( GraphQL Query) }
export default function Component() { const loaderData = useLoaderData<typeof loader>(); const actionData = useActionData<typeof action>(); // このルートに表示したい UIを定義する } export async function action() { // データを更新する( GraphQL Mutation) } Route app/routes/ 内の1ファイル 3:05
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
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
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<typeof action>(); return ( <Form method="post"> <input type="text" name="visitorsName" /> {data ? data.message : "Waiting..."} </Form> ); } loaderと同じインター フェース フォームリクエスト受付専 用関数 3:50
Fullstack Data Flow https://remix.run/docs/en/2.5.1/discussion/data-flow 4:05
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
認証は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
Remix💿を学んで Web標準(というかHTML) に再入門した事例 4:50
テーブルで1行1フォームを作りたい 5:05
私たちのフォーム周り事情 in Remix💿 • 基本は古き良き `<form>` で、実際にはSPA的な動作をサポートするため に薄くラップした `<Form>` を使う
• フォーム管理にはremix-validated-formを使っている ◦ https://www.remix-validated-form.io/ ◦ Zodで書いたスキーマをバリデーションに利用するためのアダプ ター • 非制御コンポーネント縛りで頑張ることにしている ◦ JavaScriptのロードが完了する前からユーザーが触れたほうが Remixっぽい 5:20
the 愚直 <tr> <Form action="post"> <td> <input type="hidden" id="id" name="id"
value="1111" /> </td> <td>2023-11-23</td> <td><input type="text" id="a" name="a" /></td> <td><input type="text" id="b" name="b" /></td> <td><input type="text" id="c" name="c" /></td> <td><input type="button" value="送信" /></td> </Form> </tr> tr > form > td > input 5:35
InvalidなHTMLとしてバチクソ怒られた (それはそう) 5:50
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
form属性を使う <tr> <td> <form id="form1" action="post"> <input type="hidden" id="id" name="id"
value="1111" /> </form> </td> <td>2023-11-23</td> <td><input form="form1" type="text" id="a" name="a" /></td> <td><input form="form1" type="text" id="b" name="b" /></td> <td><input form="form1" type="text" id="c" name="c" /></td> <td><input form="form1" type="button" value="送信" /></td> </tr> tr > td > form#form1 > input[form=”form1”] tdの中にある分には valid扱い form要素のid属性に指定した値を input要素のform属性に指定すると form要素の外側にある input要素も紐付けられる 6:20
We got Kotonaki. 6:35
改めて見てみる 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
HTMLど素人ワイ、 15年前(2009)に質問されて 10年前(2014)に回答された StackOverflowに救われる 7:05
恥の多い人生を送ってきました • どこかWeb標準を軽視していた自分に気付かされる機会が増えた • Remixで開発していると、Web標準を学ぶ機会が多く得られる • MDNを参照する頻度が増えるごとに、RemixやReactが死んでも使 えるスキルが手元に残る • ありがとうRemix、ありがとうWeb標準、これからもよろしく
7:20
1年間やってきて • 通信周りの非同期処理について頭を悩ませる頻度が激減した • よりプロダクトが事業に与えるバリューについて考える時間が増え た • 昔よりもMDNと仲良くなった気がする • Remixは愚直で退屈なフレームワークなのかもしれない
• 僕はフレームワークよりプロダクト、プロダクトより事業そのもの にエキサイトしたいので、フレームワークは退屈でもいい • Remix、一度お試しください 7:35
おまけ Remix💿のバージョンアップ事情 (時間がなければ割愛します) 7:50
React Router被害者の会 • RemixのコアライブラリでもあるReact Routerは、アップグレード 体制がちょっと悪名高かった • 特にv3→v4でごっそり変わって、結局追従できなかったという人も https://twitter.com/mizchi/status/856797318930026497 8:05
Remixでどうなったの • 2023年9月にv2が出たので振り返ってみる ◦ https://remix.run/blog/remix-v2 • 大きめのBreaking Changeはあったがフォローが手厚かった印象 8:20
内容自体は大小色々あった • アップグレードガイドを見てもらうとわかるけど、変更自体はめ ちゃくちゃあった ◦ https://remix.run/docs/en/2.5.1/start/v2 • これをビッグバンリリースしていたら、たぶんみんなブチ切れてい たと思う •
実際にはそうならないための手厚い配慮が行われた 8:35
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
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
Shopify買収の影響かも • メジャーバージョンもう1回分くらいは注視してもいいかもしれな いけど、ひとまず今回は慎重だったように見えた • 2022年10月にShopifyに買収されたのが良い影響になったのかも ◦ https://remix.run/blog/remixing-shopify • ShopifyのECサイト自作用SDK、HydrogenがRemixベースになった
• あんまりにも非互換なアップグレードをしてしまうと、普通に ShopifyのB2B事業の顧客に迷惑がかかるので、迂闊にビッグバンリ リースできなくなったのでは 9:20
Shopifyは堅実に進めていくイメージ • 以前、Shopifyアプリの内部実装を徐々にReact Nativeに置き換え ていくプロジェクトがあったりした ◦ https://shopify.engineering/migrating-our-largest-mobile- app-to-react-native • 顧客へ悪影響が出やすいビッグバンリリースは避け、たとえ技術的
に困難な道になろうと漸進的に進めていく文化があるように感じた • Remixもそんな感じで進めていってほしい(期待) 9:35
完 9:50
We are hiring! • ソフトウェアエンジニアを積極採用中です! • カジュアル面談お待ちしてます → @NkznにDMください •
求人情報はこちら Findy HRMOS monicle.co.jp 10:00