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.8k
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
Cloudflare Workers で作る専門性特化型 MCP サーバー / workers-specialist-mcp
nkzn
1
95
経済メディア編集部の実務に小さく刺さるAI / small-ai-with-editorial
nkzn
2
930
Remix × Cloudflare Pages × Sentry 奮闘記 / remix-pages-sentry
nkzn
1
1.8k
Cloudflareスタックで月間1200万UUの経済メディアにアバター画像生成サービスを作る / Cloudflare Developer Platform for AI avatar service
nkzn
7
3.9k
5分で流し読むCloudflare Developer Platform
nkzn
3
390
次世代Web認証「パスキー」 / mo-zatsudan-passkey
nkzn
32
18k
パスキーについて今日時点の僕が知っていること / What I Know About Passkeys as of Today
nkzn
8
2.9k
青い空の歩き方 / Flying in the bluesky
nkzn
1
330
SPAの歴史とRemix SPAモードという到達点 / the SPA's chronicle reaches to remix
nkzn
48
18k
Other Decks in Technology
See All in Technology
Modern Linux
oracle4engineer
PRO
0
150
Practical Agentic AI in Software Engineering
uzyn
0
110
Automating Web Accessibility Testing with AI Agents
maminami373
0
1.3k
Android Audio: Beyond Winning On It
atsushieno
0
2.4k
JTCにおける内製×スクラム開発への挑戦〜内製化率95%達成の舞台裏/JTC's challenge of in-house development with Scrum
aeonpeople
0
250
Terraformで構築する セルフサービス型データプラットフォーム / terraform-self-service-data-platform
pei0804
1
190
Generative AI Japan 第一回生成AI実践研究会「AI駆動開発の現在地──ブレイクスルーの鍵を握るのはデータ領域」
shisyu_gaku
0
310
【NoMapsTECH 2025】AI Edge Computing Workshop
akit37
0
220
バイブスに「型」を!Kent Beckに学ぶ、AI時代のテスト駆動開発
amixedcolor
2
580
研究開発と製品開発、両利きのロボティクス
youtalk
1
530
「Linux」という言葉が指すもの
sat
PRO
4
140
LLM時代のパフォーマンスチューニング:MongoDB運用で試したコンテキスト活用の工夫
ishikawa_pro
0
160
Featured
See All Featured
Thoughts on Productivity
jonyablonski
70
4.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
236
140k
Navigating Team Friction
lara
189
15k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
GraphQLとの向き合い方2022年版
quramy
49
14k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
GraphQLの誤解/rethinking-graphql
sonatard
72
11k
Raft: Consensus for Rubyists
vanstee
140
7.1k
Typedesign – Prime Four
hannesfritz
42
2.8k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
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