å人ããã°ã®é床æ¹åèš
by reu · 2026/5/15
Next.js 16 å人ããã°ãçéåãã話 â èšäºè©³çްã 3.8s â 73ms ã«çž®ãããŸã§ TL;DR - é ããŠè©°ãŸã£ãŠããã€ã³ãã人éãåå ç¹å®ããã®ããŸã æ©ãæ°ããã - Next.js 16 + Vercel + Prisma ã§åãããŠããã®ããã°ïŒèªåèªèº«ïŒã倿®µã§é床æ¹åãã - äž»ç¯ã¯ ãISR ã宣èšããã®ã«å¹ããŠãªãã£ãã ããš â ã§åŸ©æŽ» - èšäºè©³çް: 3.8s â 73msïŒã40åïŒ / weather API: 427ms â 49msïŒã9åïŒ ãªã©ã®å¹æ - Next.js 16 ã§ ã®ã·ã°ããã£ãå€ãã£ãŠãå°å³ãªèœãšã穎ã ç°å¢ - Next.js 16.2.3ïŒTurbopackïŒ - Vercel ãã¹ãã£ã³ã° - Prisma + SupabaseïŒDB + Auth + StorageïŒ - TypeScript / Tailwind CSS ãã£ãããšç·èЧ | | æã¡æ | 广 | |---|---|---| | 1 | PostList ã®ã¯ãšãªã ã§ãã£ãã·ã¥ | ãããã§æ¯ãªã¯ãšã¹ã DB ãå©ããªããªã£ã | | 2 | ã ã§ dedupe | ãªã¯ãšã¹ãå ã® DB åŸåŸ© 2 å â 1 å | | 3 | ã ã§æ°žç¶ãã£ãã·ã¥ | ã® HTTP åŸåŸ©ã¹ããã | | 4 | æçš¿ç³» API ã§ / | ãã£ãã·ã¥ç¡å¹åãæç€ºå | | 5 | EditButton ã® â åãæ¿ã | ã® 812ms ãæ¶æ» | | 6 | å€©æ° fetch ã ã§é å»¶ | æç»ãããã¯è§£æ¶ïŒè£ 食ãªã®ã§åŸã§ååïŒ | | 7 | 㫠远å | ãæ»ããæŒäžæã® RSC åååŸ 1.9s ãæ¶æ» | | 8 | Yusei Magic ã | woff2 preload 37 å â 7 å | | 9 | ã§å šèšäº SSG | èšäºè©³çް 3.8s â 73ms | | 10 | ã Edge Runtime + | 427ms â 49ms | 以äžãç¹ã«åŠã³ã倧ããã£ããã®ãããã¯ã¢ããããŠæžãã --- â ããŒã¿ååŸããã£ãã·ã¥ããïŒ + ïŒ ãããããŒãžã®ãæè¿ã®æ¯èšãã»ã¯ã·ã§ã³ãã¢ã¯ã»ã¹ããšã« Prisma ãå©ããŠããã ã§ 1 æ¥ãã£ãã·ã¥ + tag ã§æç€ºç Žæ£ã§ããæ§æã«ããã æŽæ°æã¯ POST/PUT ã®ãšã³ããã€ã³ãã§ ãåŒãã§æç€ºç Žæ£ããã > â ïž Next.js 16 ãã 㮠第äºåŒæ°ãå¿ é ã«ãªã£ãŠããã 㯠cacheLife ãããã¡ã€ã«åã§ãæ°žç¶ãã£ãã·ã¥çžåœã®æåãããã«æ°ä»ãããã«ããèœã¡ãã > > ãŸã ã® ãš ã®æ¬äœã§åã slug ã® ã 2 åå©ããŠããã®ã§ã ã§ dedupe ããã 㯠åäžãªã¯ãšã¹ãå ã§åãåŒæ°ãªãçµæãåå©çšããä»çµã¿ãISR ãå¹ããŠããã°ãããã DB ã¯è§Šããªããããã£ãã·ã¥åçææã«ã ãå¹ãä¿éºãšããŠå ¥ããã --- â¡ Markdown ã¬ã³ããªã³ã°çµæãæ°žç¶ãã£ãã·ã¥ ã¯å éšã§ ã䜿ããèšäºå ç»åã®å®ãµã€ãºããªã¢ãŒããã HTTP ã§ååŸããŠããããããç»åææ°åèµ°ãã®ã§çµæ§éãã ã§ ãããŒã«æ°žç¶ãã£ãã·ã¥åããã ãããŒã«å«ãŸããã®ã§ãèšäºæŽæ°æã¯èªåã§å¥ããŒã«ãªãåèšç®ããããå€ãããŒã®ãã£ãã·ã¥ã¯ Next.js åŽã§æŸçœ®ãããã --- ⢠EditButton ã® 812ms åæž ãã©ãŠã¶ã® DevTools ã§ Network ãèŠãŠããããèšäºããŒãžã«é£ã¶ãã³ã« ãžã® fetch ã 812ms ããã£ãŠãããç¯äººã¯ããã 㯠Supabase ã®èªèšŒãµãŒããŒã«æ¯ååãåãããã®ã§é ããäžæ¹ 㯠localStorage / Cookie ããæ¢åã»ãã·ã§ã³ãèªãã ãã§ã»ãŒ 0msã ãã®ãã¿ã³ã®çšéã¯ããã°ã€ã³äžãªãç·šéãã¿ã³ã衚瀺ãããã ããå®éã«ç·šéãå®è¡ãã API ã«ãŒãã§ã¯å¥é ã§æ€èšŒãããã®ã§ãUI 衚瀺å€å®ãšããŠã¯ ã§ååã ãããã¯ãŒã¯ã¿ããã ã®ãªã¯ãšã¹ãããšæ¶ããã --- â£ è£ é£Ÿçš API ã¯æç»åŸã§ããïŒïŒ èæ¯ã®ç©ºã®è²ã倩æ°ã§å€ããè£ é£Ÿãããã ã峿 fetch ããŠããããã ããã¯è£ 食ãªã®ã§ãã¡ã€ã³æç»åŸã§ååã ã§ãã©ãŠã¶ã®ã¢ã€ãã«æéã«é å»¶ããã 㯠Safari ã®å€ãããŒãžã§ã³ã§æªå¯Ÿå¿ãªã®ã§ã ã§ãã©ãŒã«ããã¯ããŠããã --- â€ ãæ»ãããã¿ã³ã§ 1.9 ç§ â ã®èœãšã穎 èšäºè©³çްãããæ»ãããæŒããšããããã«æ»ãã®ã«æ¯å 1.9 ç§ããã£ãŠãããDevTools ã§èŠããš ãšãã URL ã« GET ãé£ãã§ããã ãã㯠React Server Components ã® payload ãååŸãã Next.js ã®æåãæ¬æ¥ã¯ Router Cache ããå³åŸ©å ãã¹ããšãããæ¯ååååŸããŠããã åå 㯠Next.js 16 ã® Router Cache ã®ããã©ã«ãèšå®ã | ããŒãžçš®å¥ | ããã©ã«ãã® staleTimes | |---|---| | Static | 5 å | | Dynamic | 0 ç§ â å³ expire | ãã®ãµã€ãã®ããã㯠AboutMe ã ã䜿ã£ãŠãé¢ä¿ã§ Dynamic æ±ãã«ãªã£ãŠãããRouter Cache ã®ä¿ææéã 0 ç§ã ã£ãã ã§æç€ºçã«æ¡åŒµããã ããã§æ»ããã¿ã³æŒäžæã« Router Cache ããå³åŸ©å ãããããã«ãªãã ã®åååŸãæ¶ããã --- ⥠ãã©ã³ãã® preload ã 37 åããã£ã ãããã¯ãŒã¯ã¿ãã§ ãèŠããš 37 å ã® preload ãèµ°ã£ãŠããã ã ã§äœ¿ã£ãŠããããæ¥æ¬èªãã©ã³ãã® Google Fonts CSS 㯠ã§å€§éã® segment ã«åå²ãããŠãããNext.js ãããããå šãŠèªå preload ããŠããã ã«ããããšã§ãrevalidate = 86400curl -I cache-control: private, no-cache, no-store, max-age=0, must-revalidate x-vercel-cache: MISS cf-cache-status: DYNAMIC MISSage: 0await paramsforce-staticts // ãã£ãŠããŸã£ã export const dynamic = "force-static"; export const revalidate = 86400; [slug]generateStaticParamsforce-staticforce-staticgenerateStaticParamsgenerateStaticParamsforce-staticgenerateStaticParamsts // app/posts/[slug]/page.tsx import { getAllPublishedSlugs } from "@/lib/queries"; export const revalidate = 86400; export async function generateStaticParams() { const slugs = await getAllPublishedSlugs(); return slugs.map((slug) => ({ slug })); } ts // lib/queries.ts export async function getAllPublishedSlugs(): Promise { const posts = await prisma.post.findMany({ where: { published: true }, select: { slug: true }, }); return posts.map(({ slug }) => slug); } generateStaticParamsdynamicParams = truecurl -I [1] TTFB=1.071s x-vercel-cache: HIT age: 0 [2] TTFB=0.341s x-vercel-cache: HIT age: 2 [3] TTFB=0.056s x-vercel-cache: HIT age: 3 x-vercel-cache/api/weatheripapi.co/json//api/weather?lat=...&lon=...x-vercel-ip-latitudex-vercel-ip-longitudets // app/api/weather/route.ts export const runtime = "edge"; export async function GET(request: NextRequest) { const headerLat = request.headers.get("x-vercel-ip-latitude"); const headerLon = request.headers.get("x-vercel-ip-longitude"); const lat = parseFloat(headerLat ?? ""); const lon = parseFloat(headerLon ?? ""); // 0.1床ïŒçŽ 11kmïŒã«äžžã㊠CDN ãã£ãã·ã¥ããŒãå ±æãããããã const finalLat = Number.isFinite(lat) ? Math.round(lat 10) / 10 : 35.6812; const finalLon = Number.isFinite(lon) ? Math.round(lon 10) / 10 : 139.7671; const res = await fetch( , { next: { revalidate: 600 } } ); // ... return NextResponse.json(data, { headers: { "Cache-Control": "public, max-age=600, s-maxage=600, stale-while-revalidate=3600", }, }); } runtime = "edge"/api/weatheripapi.co [1] TTFB=1.061s age: 0 (Edge cold start) [2] TTFB=0.219s age: 0 [3] TTFB=0.049s age: 1 â 49ms! /api/weatherrevalidatex-vercel-cache: MISSforce-staticgenerateStaticParamsrevalidateTag"max"getSessiongetUserrequestIdleCallbackunstable_cache'use cache'probe-image-size` ã®çµæã DB ã«æ°žç¶åããïŒæçš¿æã®ã¿å®è¡ããèšèšïŒ åèãªã³ã¯ - Next.js: generateStaticParams - Next.js: staleTimes - Next.js: revalidateTag - Vercel: Edge Functions geolocation headers - Supabase: getSession vs getUser
