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
IoTハンズオンの舞台裏
shirouz
2
160
推論の観測、できていますか? 〜 Google Cloud Gemini Enterprise Agent Platformで 3つの Gemini モデルを実測して踏んだ、評価の罠 〜
shukob
PRO
0
170
Autonomous AI Databaseサービス・アップデート(FY27)/ adb-service-update-jp-fy27
oracle4engineer
PRO
0
130
Where Is JetBrains AI Heading- — Central CLI, Air Alpha, and the Agentic Development Stack
x5gtrn
PRO
0
140
Beyond the Hype: Practical AI for Your Oracle Database with MCP
thatjeffsmith
1
280
[DroidKaigi 2026] Making UI specifications visible: Android UI development in the AI agent era supported by Compose Screenshot Testing and galleries
syarihu
0
600
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
160
Bet AI Day 2026丨AIを「使う」から、AIが「働く」へ ― LayerXが進める「組織AI」の社会実装
layerx
PRO
3
2.8k
振り返りこそエンジニアの本領
negima
0
330
設計の世代交代を乗り越える、14年続くAndroidアプリの開発戦略
sansantech
PRO
1
150
From Vanilla Kubernetes to a Batteries-Included Platform: Developer Experience at 1,300+ Clusters
yosshi_
0
620
データエンジニアリングワークショップ:Auto LoaderとSparkで学ぶデータパイプライン構築
databricksjapan
PRO
0
210
Featured
See All Featured
Utilizing Notion as your number one productivity tool
mfonobong
4
570
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
870
Balancing Empowerment & Direction
lara
6
1.3k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.2k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.1k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
Side Projects
sachag
455
43k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.3k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
520
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
440
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に準拠した思想で実装されているので対象的になっている
ご清聴ありがとうございました 🎉