Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
RemixでWeb標準を学んだ1年間 / First year with Remix
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Yukiya Nakagawa
January 23, 2024
Technology
9.4k
22
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RemixでWeb標準を学んだ1年間 / First year with Remix
フロントエンドの技術選定 ~2023を振り返る~ Lunch LT での発表資料です
https://findy.connpass.com/event/306714/
Yukiya Nakagawa
January 23, 2024
More Decks by Yukiya Nakagawa
See All by Yukiya Nakagawa
視野はAIに、視座は人に / ai-for-breadth-humans-for-perspective
nkzn
6
3.2k
明日の講演、こうやって作ってます - KomeKaigi 2026招待講演のメイキング / niigata-5min-tech-20261030
nkzn
0
59
AIがコードを書いてくれるなら、新米エンジニアは何をする? / komekaigi2025
nkzn
25
20k
JS Temporalを学ぶ人のための JSR-310入門 / jsr310-for-temporal
nkzn
0
130
Cloudflare Workers で作る専門性特化型 MCP サーバー / workers-specialist-mcp
nkzn
1
230
経済メディア編集部の実務に小さく刺さるAI / small-ai-with-editorial
nkzn
3
1.3k
Remix × Cloudflare Pages × Sentry 奮闘記 / remix-pages-sentry
nkzn
1
3.2k
Cloudflareスタックで月間1200万UUの経済メディアにアバター画像生成サービスを作る / Cloudflare Developer Platform for AI avatar service
nkzn
7
5.7k
5分で流し読むCloudflare Developer Platform
nkzn
3
500
Other Decks in Technology
See All in Technology
Software Engineering in an AI-Driven World
erikjhordan_rey
0
130
サボる子はいねぇがー!AgentCoreハーネスの脆弱性に学ぶ、エージェントの入力バリデーション
iwamot
PRO
5
300
SLOを阻む不安
sraku2159
0
230
AWS Quick 入門 | 目指せ Quick マスター 01
inariku
PRO
1
140
プロダクションコードにおける encoding/json から encoding/json/v2 へのスムーズな移行
sansantech
PRO
1
150
HQ駆動開発で最高のAI-Contextを作ろう
sansantech
PRO
1
110
デザインレビューは自動化できるのか?─ Flutter × Figma で UI 品質保証を考える
techiro
2
820
レガシーコードに対する loop engineering的なAI開発プロセス導入について
kubell_hr
0
280
TSKaigi Sendai 2026 - tsgo時代のTypeScript Playgroundはどう動くか
teamlab
PRO
0
110
並列度を下げたら速くなった — go build の重複コンパイルを実測で見る
tomoaki25
2
900
Microsoft Entra Kerberos で実現するクラウド デバイス管理
tamaiyutaro
2
650
AWS構成から考えるWebセキュリティ ― WordPressの構築経験から考える公開範囲と更新運用【JAWS FESTA 2026 in AKITA】
cscengineer
PRO
2
360
Featured
See All Featured
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
560
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
GitHub's CSS Performance
jonrohan
1033
470k
Optimizing for Happiness
mojombo
378
71k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
530
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.2k
Test your architecture with Archunit
thirion
2
2.5k
Large-scale JavaScript Application Architecture
addyosmani
516
110k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
600
Chasing Engaging Ingredients in Design
codingconduct
0
390
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