Next.js 16.2 升級實錄

最近 Next.js 16.2 發佈了(2026/3/18),release notes 裡面寫了一堆效能改善——dev startup 快 87%、rendering 快 25-60%、200+ Turbopack bug fixes。
聽起來很厲害,但數字是官方的環境測出來的,跟你我的專案可能差很多。所以我就拿自己的 blog(一個中小型 Next.js App Router 專案,24 routes、Three.js 3D 頁面、Drizzle ORM + Postgres)來實際升級,看看到底有沒有感覺。
TL;DR
先上結論,懶得看全文的可以直接看這張表:
| 指標 | 16.1.2 | 16.2.0 | 變化 |
|---|---|---|---|
| Build time(3 次平均) | 9.64s | 8.57s | -11.1% ✓ |
.next 目錄大小 | 29MB | 31MB | +6.9% |
| Dev cold start(3 次平均) | 1285ms | 559ms | -56.5% ✓✓✓ |
| 測試(80 tests) | 549ms | 451ms | -17.9% ✓ |
Dev cold start 的改善最誇張,直接砍半還多。Build time 也有穩定的 11% 改善。.next 大了一點點但可以接受。
值不值得升?值得,尤其如果你每天 next dev 開好幾次的話 (´・ω・`)
1. Next.js 16.2 帶來了什麼
效能改善
- Dev startup 加速:官方說 ~87% faster(對,你沒看錯,是 87%),主要是 Turbopack 的啟動優化
- Server Components rendering 加速:他們改了 React 的
JSON.parsereviver 實作方式。原本的 reviver callback 每對 key-value 都會跨越 V8 的 C++/JS boundary,即使是空的 reviver 也會讓JSON.parse慢 4 倍。新的做法是先JSON.parse()再用純 JS 遞迴走一遍,實測 rendering 快 25-60% - ImageResponse 加速:基本圖片 2x,複雜圖片最高 20x faster
開發體驗改善
- Server Function Logging:dev 的時候 terminal 會顯示 Server Action 的執行資訊(函式名稱、參數、耗時、檔案位置)。這個超實用,以前 debug Server Action 真的很痛苦
- Hydration Diff Indicator:hydration mismatch 的 error overlay 現在會用
+ Client/- Server格式清楚標示差異,不用再自己猜哪邊不一樣了 - Error Cause Chain:error overlay 會顯示完整的
Error.causechain,最多 5 層 --inspectfornext start:16.1 支援next dev --inspect,16.2 延伸到 production server
新 API
<Link transitionTypes>:可以傳 View Transition 的 type,做不同方向的 page transition 動畫unstable_catchError():比error.tsx更細粒度的 error boundary,可以放在 component tree 的任何位置unstable_retry():error.tsx 的新 prop,比reset()更強——會同時router.refresh()重新 fetch 資料- Adapters API stable:讓部署平台可以自定義 build process
Turbopack(200+ fixes)
- Server Fast Refresh(server-side 的 HMR)
- Web Worker Origin 支援
- Subresource Integrity 支援
- Dynamic imports 的 tree shaking
AI 相關
create-next-app內建AGENTS.md- Browser log forwarding(把瀏覽器 error 轉發到 terminal,方便 AI agent debug)
- Dev Server Lock File(防止同時開兩個 dev server)
- Experimental Agent DevTools
2. 升級過程
改了什麼
其實改動超少,就 package.json 兩行:
- "next": "16.1.2",
+ "next": "^16.2.0",
- "eslint-config-next": "16.1.2",
+ "eslint-config-next": "^16.2.0",然後 pnpm install,完事。React 19.2.3、Tailwind v4、Drizzle ORM 這些都不用動。
有沒有踩坑
有,兩個小坑:
坑 1:NextMiddleware 型別變嚴格了
測試裡面 mock auth 函式回傳 null 的寫法:
// 16.1.2 OK,16.2.0 報錯
vi.mocked(auth).mockResolvedValue(null);
// TS2345: Argument of type 'null' is not assignable to parameter of type 'NextMiddleware'修法很簡單,加個 as never:
vi.mocked(auth).mockResolvedValue(null as never);這不是什麼大問題,就是 Next.js 16.2 收緊了 middleware 相關的型別定義。但如果你的測試也有類似的 mock 寫法,升級後可能會遇到。
坑 2:新增 react-hooks/set-state-in-effect ESLint 規則
新版 eslint-config-next 加了一條規則,禁止在 useEffect 裡面同步呼叫 setState。我的 ThemeToggle 元件用了經典的 mounted pattern:
// 16.2.0 eslint error: Calling setState synchronously within an effect
// can trigger cascading renders
useEffect(() => {
setMounted(true);
}, []);改用 useSyncExternalStore 就好了:
const emptySubscribe = () => () => {};
const mounted = useSyncExternalStore(emptySubscribe, () => true, () => false);這個改法其實更 React-idiomatic——useSyncExternalStore 的第三個參數是 server snapshot(回傳 false),client 回傳 true,完美取代了 useEffect + useState 的 mounted 模式。
說實話,看到這條新 lint rule 我還蠻開心的。之前寫過一篇關於 Factory AI 禁用 useEffect 的文章,裡面提到的 anti-pattern 跟這條規則的精神完全一致——useEffect 裡面 setState 會多觸發一次不必要的 re-render (╯°□°)╯︵ ┻━┻
proxy.ts 相容性
我的 proxy.ts 用了 NextRequest / NextResponse 做 rate limiting,升級後完全不用改,直接通過。next.config.ts 也不用改(我的設定本來就很簡單,只有 images.remotePatterns)。
3. 效能實測比較
測試環境:macOS、Apple Silicon、pnpm、每次測量前都 rm -rf .next 清快取。
Build Time
每個版本跑 3 次 clean build:
| 次數 | 16.1.2 | 16.2.0 |
|---|---|---|
| #1 | 10.545s | 8.828s |
| #2 | 9.406s | 8.497s |
| #3 | 8.982s | 8.393s |
| 平均 | 9.64s | 8.57s |
改善:-11.1%
官方沒有特別宣稱 build time 的改善,但從 Turbopack 的 200+ fixes 來看,bundling 效率確實有提升。11% 在中小型專案已經蠻有感的了,大型專案可能會更明顯。
另外注意到 16.2 的 build output 多了一行 Finished TypeScript in 3.8s,之前沒有這個——看起來 TypeScript 檢查的時間被獨立出來顯示了,debug build 效能更方便。
Dev Cold Start
每個版本跑 3 次 rm -rf .next && next dev:
| 次數 | 16.1.2 | 16.2.0 |
|---|---|---|
| #1 | 1395ms (Ready 861ms) | 670ms (Ready 355ms) |
| #2 | 1088ms (Ready 629ms) | 511ms (Ready 225ms) |
| #3 | 1373ms (Ready 854ms) | 496ms (Ready 220ms) |
| 平均 | 1285ms | 559ms |
改善:-56.5%
這個改善是最有感的。官方宣稱 87% faster(在 default application 上),我的專案是 56.5%——沒有到 87% 但也非常顯著。差異可能是因為我的專案有 Three.js 等較大的 dependency。
Next.js 自己報告的 "Ready in" 時間從 ~780ms 降到 ~267ms,這更接近官方的數字。外部測量的時間差異(包含 pnpm 的 overhead)會稀釋一些。
Bundle Size
| 指標 | 16.1.2 | 16.2.0 |
|---|---|---|
.next 目錄 | 29MB | 31MB |
大了 2MB(+6.9%),可能是 Turbopack 新功能(SRI support 等)的 runtime code。不是什麼問題。
測試速度
| 指標 | 16.1.2 | 16.2.0 |
|---|---|---|
| 80 tests | 549ms | 451ms |
快了 17.9%。雖然測試跑的是 Vitest 不是 Next.js 的 build pipeline,但底層的 TypeScript transform 應該也受惠於 Turbopack 的改善。
4. 值不值得升
結論:升,沒有懸念
- 升級成本極低:改兩行
package.json,可能遇到一兩個型別/lint 的小調整 - 效能改善實質有感:特別是 dev cold start,每天省下的等待時間累積起來很可觀
- 新的 DX 功能很實用:Server Function Logging 和 Hydration Diff 這兩個我等很久了
- 沒有 breaking changes:
proxy.ts、App Router、所有 API routes 都不用改
誰特別應該升
- 每天頻繁重啟 dev server 的人(cold start 改善 50%+ 很有感)
- 有複雜 Server Components 的專案(rendering 加速 25-60%)
- 常在 debug hydration mismatch 的人(新的 diff indicator)
技術債提醒
我的專案還在用已經 sunset 的 @vercel/postgres,這次升級刻意沒有一起遷移到 @neondatabase/serverless,保持升級範圍最小化。如果你也還在用 @vercel/postgres,記得排進 backlog——它不會突然壞掉,但官方已經不再維護了。
整體來說,Next.js 16.2 是一個「升了不會痛、升了真的有感」的版本。官方宣稱的效能數字在真實專案上打了點折扣(87% → 56.5% dev startup、50% → 11% build),但方向是對的,而且 DX 的改善是實實在在的。
推薦大家找個空檔升一下,大概 10 分鐘就搞定了 ヽ(✿゚▽゚)ノ