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
App Routerの紹介
Search
Yohei Iino
February 23, 2024
Technology
160
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
App Routerの紹介
Yohei Iino
February 23, 2024
More Decks by Yohei Iino
See All by Yohei Iino
1年半放置したExpo製アプリを最新化してみた
wheatandcat
0
120
作成中のFlutterアプリの中間発表
wheatandcat
0
95
最近読んだ技術書を簡単紹介
wheatandcat
0
120
ユニバーサルリンク/アプリリンクを使ってQRコードでゲストログインできるようにする
wheatandcat
0
390
Firebase App Checkを実装したので紹介
wheatandcat
0
340
PlanetScaleの無料プランがなくなるので、NeonとTiDBを試してみた
wheatandcat
0
430
Flutter HooksとRiverpodの解説
wheatandcat
0
590
T3 Stack(応用編: Next Auth & SSRの実装紹介)
wheatandcat
1
420
Flutter × GraphQLでアプリを作ってみる
wheatandcat
0
350
Other Decks in Technology
See All in Technology
Backstageでつくるセルフサービスな社内開発基盤
kikunosuke75
1
360
深夜のクラウド懺悔室 1:29:300 or 1:0:0
kazzpapa3
0
190
『止めない』を設計する — 制約の中で、事業の根幹を支える判断
hiroyaterui
0
220
Autonomous AI Databaseサービス・アップデート(FY27)/ adb-service-update-jp-fy27
oracle4engineer
PRO
0
130
2026-09-04 SRE Tech Talk #15 怠惰なTerraform / Lazy Terraform
masasuzu
0
220
AI時代に、プロダクトの数だけ積み上がる所有コストをどうエンジニアリングするか / Engineering the Cost of Ownership
kzkmaeda
1
1.1k
コスト最適化の「めんどくさい」を AWS FinOps Agent でチョット楽にする
classmethod_kaz
0
270
Multica × 長期記憶:40個のミニプロジェクト管理
eiei114
1
200
AIエージェントの開発・提供におけるセキュリティリスクの論点と対策
flatt_security
2
600
「重なり」は迎える側がつくる ― 人もAIエージェントも歓迎するプロダクトエンジニアリング ―
go0517go
PRO
0
260
Bet AI Day 2026丨Agentは、「金融」という巨大産業の何を変えられるのか
layerx
PRO
0
1.2k
Adaptive Warehouse を今すぐ導入すべき理由と迷ったときの判断基準
__allllllllez__
0
110
Featured
See All Featured
エンジニアに許された特別な時間の終わり
watany
108
250k
Paper Plane (Part 1)
katiecoart
PRO
1
11k
Discover your Explorer Soul
emna__ayadi
2
1.3k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
430
Scaling GitHub
holman
464
140k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
The World Runs on Bad Software
bkeepers
PRO
72
12k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Transcript
App Routerの紹介 Press Space for next page
自己紹介 📝 飯野陽平(wheatandcat) 🏢 法人設立(合同会社UNICORN 代表社員) 💻 Work: シェアフル株式会社CTO 📚
Blog: https://www.wheatandcat.me/ 🛠 今までに作ったもの memoir ペペロミア MarkyLinky
App Routerとは? Next.js 13.4で追加された新しいルーティング機構 従来のNext.jsのルーティングはPage Router RSC(React Server Components)の使用を前提と設計
RSC(React Server Components) とは? Reactでサーバーサイドでレンダリングできるコンポーネントを宣言できる仕組み 元々、Reactにはクライアントサイドでレンダリングするクライアントコンポーネントしかなかった SSRは、クライアントコンポーネントをサーバーサイドでレンダリングする仕組み RSCを使用することでサーバーサイド固有の機能を実装できる 例えばReact内で直接データベースにアクセスすることなどが可能 逆にRSCではクライアントサイド固有の機能は使用できない
例えば、useStateやuseEffectなどのHooksは使用できない 宣言した時点でエラーになる RSCで宣言されたコンポーネントはブラウザ側で読み込みbundleされたJavaScriptには含まれないため、読 み込むファイルサイズは小さくなる
App Routerのルーティング基本機構 従来のPage Routerのルーティング機構 App Routerのルーティング機構 src └─ pages ├─
index.tsx → / └─ items ├─ [id].tsx → /items/[id] └─ [id] └─ share.tsx → /items/[id]/share src └─ app ├─ page.tsx → / └─ items └─ [id] ├─ page.tsx → /items/[id] └─ share └─ page.tsx → /items/[id]/share
ルーティング毎に動的にfavicon、OG画像を変更する App Routerのルーティング機構だと以下のように設定が可能 以下、書き方の参考 src/app/icon.tsx src └─ app ├─ layout.tsx
→ 共通設定 └─ items └─ [id] ├─ icon.tsx → 動的favicon を変更 └─ opengraph-image.tsx → 動的OG 画像を変更
データアクセス & レンダリングの構造① App RouterはデフォルトはRSCでレンダリングされる、以下、コードの例 export default function Home() {
return ( <div className="container"> <h1 className="text-5xl"> Sample App </h1> <CrudShowcase /> </div> ); } async function CrudShowcase() { const session = await getServerAuthSession(); if (session?.user) { const url = await api.url.existsByUserId.query({userId: String(session?.user.id)}); if (url) redirect(`/schedule/${String(url?.id)}`); } return <CreateUrl />; }
データアクセス & レンダリングの構造① App RouterはデフォルトはRSCでレンダリングされる、以下、コードの例 async function CrudShowcase() { export
default function Home() { return ( <div className="container"> <h1 className="text-5xl"> Sample App </h1> <CrudShowcase /> </div> ); } const session = await getServerAuthSession(); if (session?.user) { const url = await api.url.existsByUserId.query({userId: String(session?.user.id)}); if (url) redirect(`/schedule/${String(url?.id)}`); } return <CreateUrl />; }
データアクセス & レンダリングの構造① App RouterはデフォルトはRSCでレンダリングされる、以下、コードの例 const session = await getServerAuthSession();
if (session?.user) { const url = await api.url.existsByUserId.query({userId: String(session?.user.id)}); if (url) redirect(`/schedule/${String(url?.id)}`); } export default function Home() { return ( <div className="container"> <h1 className="text-5xl"> Sample App </h1> <CrudShowcase /> </div> ); } async function CrudShowcase() { return <CreateUrl />; }
データアクセス & レンダリングの構造① App RouterはデフォルトはRSCでレンダリングされる、以下、コードの例 return <CreateUrl />; export default
function Home() { return ( <div className="container"> <h1 className="text-5xl"> Sample App </h1> <CrudShowcase /> </div> ); } async function CrudShowcase() { const session = await getServerAuthSession(); if (session?.user) { const url = await api.url.existsByUserId.query({userId: String(session?.user.id)}); if (url) redirect(`/schedule/${String(url?.id)}`); } }
データアクセス & レンダリングの構造② "use client"; export function CreateUrl() { const
router = useRouter(); const createMutation = api.url.create.useMutation({ onSuccess: (data) => { router.push(`/items/${data.id}`); }, }); const onCreate = useCallback(() => { createMutation.mutate(); }, [createMutation]); return ( <button className="button" onClick={onCreate} > 新しいデータを作る </button> ); }
データアクセス & レンダリングの構造② "use client"; export function CreateUrl() { const
router = useRouter(); const createMutation = api.url.create.useMutation({ onSuccess: (data) => { router.push(`/items/${data.id}`); }, }); const onCreate = useCallback(() => { createMutation.mutate(); }, [createMutation]); return ( <button className="button" onClick={onCreate} > 新しいデータを作る </button> ); }
データアクセス & レンダリングの構造② export function CreateUrl() { const router =
useRouter(); const createMutation = api.url.create.useMutation({ onSuccess: (data) => { router.push(`/items/${data.id}`); }, }); const onCreate = useCallback(() => { createMutation.mutate(); }, [createMutation]); return ( <button className="button" onClick={onCreate} > 新しいデータを作る </button> ); } "use client";
データアクセス & レンダリングの構造③ RSCではasync/awaitが使用できる RSCではhooksは使用できないのでデータ更新で使用するuseMutationはクライアントコンポーネントで実 装する必要がある RSCでデータ取得する場合は、直接データベースにアクセスが可能なので以下のように実装が可能 export default async
function Page({ params }: { params: { id: string } }) { const session = await getServerAuthSession(); const url = await api.url.exists.query({ id: params.id }); if (url === null) { // 存在しないURL の場合はトップページに戻す redirect("/"); } ... 省略
データアクセス & レンダリングの構造③ RSCではasync/awaitが使用できる RSCではhooksは使用できないのでデータ更新で使用するuseMutationはクライアントコンポーネントで実 装する必要がある RSCでデータ取得する場合は、直接データベースにアクセスが可能なので以下のように実装が可能 export default async
function Page({ params }: { params: { id: string } }) { const session = await getServerAuthSession(); const url = await api.url.exists.query({ id: params.id }); if (url === null) { // 存在しないURL の場合はトップページに戻す redirect("/"); } ... 省略
データアクセス & レンダリングの構造③ RSCではasync/awaitが使用できる RSCではhooksは使用できないのでデータ更新で使用するuseMutationはクライアントコンポーネントで実 装する必要がある RSCでデータ取得する場合は、直接データベースにアクセスが可能なので以下のように実装が可能 const url =
await api.url.exists.query({ id: params.id }); if (url === null) { // 存在しないURL の場合はトップページに戻す redirect("/"); } export default async function Page({ params }: { params: { id: string } }) { const session = await getServerAuthSession(); ... 省略
実装してみる PR: App Routerに変更する 以下、デモしながら説明 App Routerの移行で以下の処理はシンプルに実装できた例1 旧コード 新コード App
Routerの移行で以下の処理はシンプルに実装できた例2 旧コード 新コード
まとめ App RouterはRSCを前提としたルーティング機構になっている RSCを使用するとデータ取得周りはシンプルに実装できる ただ、App Routerはフロントエンド界隈では賛否両論で、当面Web文脈では議論されていきそう 一休レストランで Next.js App Router
から Remix に乗り換えた話 元々Next.jsはWeb標準のAPIに準拠していないことが問題視されていて、App Routerでより、その点が 強まった 逆にRemixはWeb標準のAPIに準拠した思想で実装されているので対象的になっている
ご清聴ありがとうございました 🎉