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
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がコードを書いてくれるなら、新米エンジニアは何をする? / komekaigi2025
nkzn
25
20k
JS Temporalを学ぶ人のための JSR-310入門 / jsr310-for-temporal
nkzn
0
120
Cloudflare Workers で作る専門性特化型 MCP サーバー / workers-specialist-mcp
nkzn
1
220
経済メディア編集部の実務に小さく刺さる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.6k
5分で流し読むCloudflare Developer Platform
nkzn
3
500
次世代Web認証「パスキー」 / mo-zatsudan-passkey
nkzn
32
19k
パスキーについて今日時点の僕が知っていること / What I Know About Passkeys as of Today
nkzn
8
3.1k
Other Decks in Technology
See All in Technology
Let's Change Our World—Again
snoozer05
PRO
6
710
推論基盤と Scale-Up Interconnect の現状と制約から俯瞰する技術動向
markunet
2
540
シンプルな設定ファイルで実現する AWS IAM Identity Center の ユーザー管理Terraformフレームワークを公開しました / Simplifying AWS IAM Identity Center User Management: An Open-Source Terraform Framework
yamaguchitk333
1
330
仕様駆動開発の、その先へ。決める力と確かめる仕組み
inariku
0
110
AI駆動開発における開発環境のセキュリティの考え方
yamahiro
2
650
Claude Code on Bedrock で統制をかける小ネタ集/claude-code-bedrock-governance-tips
emiki
1
13k
演劇と私とスクラム
chinmo
0
160
"計画的無茶振り"を通してAIネイティブ世代の新人を育てる
subroh0508
1
120
AI時代のエンジニアの情報発信〜個人の発信を組織の力に変える〜
ryo_kawamata
0
180
渡米前の準備を制す!re:Invent 2026徹底準備術 / The Ultimate Preparation Guide for re:Invent 2026
yuj1osm
1
350
キヨさん、67歳。AIコーディングエージェントに挑む
happysamurai294
0
110
Vue.jsのGitHubから学ぶ意思決定
yut0naga1_fa
1
320
Featured
See All Featured
We Are The Robots
honzajavorek
0
410
Practical Orchestrator
shlominoach
192
12k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
YesSQL, Process and Tooling at Scale
rocio
174
15k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
540
WENDY [Excerpt]
tessaabrams
14
40k
Claude Code のすすめ
schroneko
67
230k
Typedesign – Prime Four
hannesfritz
42
3.2k
Designing for humans not robots
tammielis
254
26k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
230
Design in an AI World
tapps
1
370
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.5k
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