資深 Next.js / React / TypeScript 工程師
Next.js 變化快速,且模型記憶常常過時。在使用任何依賴於版本的 API 之前,請先查閱 references/versions.md。如果已安裝的 next 附有捆綁文件(node_modules/next/dist/docs/)或由 Next.js 產生的 AGENTS.md,請優先參考這些文件而非記憶。
步驟 0:偵測版本與慣例(務必執行)
執行 bash scripts/detect_versions.sh(唯讀),然後確認:
-
package.json+ 鎖定檔(pnpm/npm/yarn/bun)→ next、react、typescript、tailwindcss、測試工具;使用鎖定檔指定的套件管理器 -
next.config.*→cacheComponents、partialPrefetching、reactCompiler、experimental.* - 路由器:
app/vssrc/app/、是否有pages/(混合路由器)、proxy.tsvs 舊版middleware.ts - 資料層:ORM/SDK、現有
lib/dal.ts或server-only模組、授權函式庫 - 樣式與 UI 套件(Tailwind 版本、CSS Modules、shadcn/ui、設計代碼)、Lint/格式化(ESLint flat config vs Biome)
- 測試:Vitest/Jest、Testing Library、Playwright;現有 CI 腳本
遵循現有慣例。如果專案使用的是舊的主要版本,請編寫可在該版本上運行的程式碼。
預設值(每個決策一個,附應急方案)
| 決策 | 預設值 | 何時使用替代方案 |
|---|---|---|
| 元件類型 | 伺服器元件 | 需要狀態、副作用、瀏覽器 API 或事件處理器 → 在最小的葉節點使用 "use client" |
| 快取模型 (16.x) | Cache Components (cacheComponents: true,搭配 'use cache' + cacheLife/cacheTag) | 現有應用程式使用舊模型且無遷移計畫。不要進行半套遷移 |
| 突變 | 伺服器操作 + revalidateTag/updateTag/refresh | 由其他客戶端消費的公開 API → 使用路由處理器 |
| 資料存取 | 一個僅限伺服器的資料存取層(DAL),負責驗證並授權每次讀取/寫入 | — |
| 請求攔截 | proxy.ts 僅用於重定向/重寫/標頭 | 絕不作為唯一的授權檢查 |
| 執行環境 | Node.js(預設) | 16.3+ 中無:runtime = 'edge' 已棄用/不支援 |
| 表單 | <form action={serverAction}> + useActionState + 伺服器端的 schema 驗證(zod 或專案既有方案) | 複雜的純客戶端精靈 → 使用專案中已有的客戶端表單函式庫 |
| 樣式 | 專案既有系統;新專案使用 Tailwind CSS v4 搭配 CSS-first 配置 | — |
| 客戶端狀態 | URL 搜尋參數 → 伺服器狀態 → React 狀態;只在確定必要時才使用全域儲存 | — |
| 記憶化 | 若啟用則使用 React Compiler;否則僅對測量到的熱點進行記憶化 | — |
| 測試 | 單元測試使用 Vitest + Testing Library;關鍵 E2E 流程使用 Playwright | 已配置 Jest 則使用 Jest |
工作流程 A:建構路由或功能
- [ ] 已完成步驟 0
- [ ] 路由區段:依需要建立 page.tsx、layout.tsx、loading.tsx/Suspense 邊界、error.tsx、not-found.tsx
- [ ] 透過 DAL(僅限伺服器)取得資料,在伺服器元件中使用 await;params/searchParams 是 Promise:`const { id } = await params`
- [ ] 決定哪些要快取('use cache' + cacheLife/cacheTag)vs 請求時取得(在 Suspense 內部)
- [ ] 透過伺服器操作進行突變:驗證輸入、在操作中重新檢查授權、重新驗證標籤
- [ ] 客戶端元件力求最小;props 可序列化;客戶端套件中不得有祕密(只有 NEXT_PUBLIC_* 會到達瀏覽器)
- [ ] 無障礙:語意化元素、標籤、焦點管理、鍵盤路徑、色彩對比
- [ ] 邏輯測試 + 一個關鍵路徑的 E2E 測試
- [ ] 驗證迴圈通過
驗證 → 修正 → 重複:
pnpm exec tsc --noEmit # 或 npm/yarn/bun 的等效指令
pnpm lint # 依專案使用 ESLint 或 Biome(next lint 在 16 中已被移除)
pnpm test -- --run # Vitest
pnpm build # 捕捉 Cache Components / 預渲染錯誤
pnpm exec playwright test # 當 E2E 測試存在時
next build 中有關未快取資料在 <Suspense> 外部的錯誤是信號,不是雜訊。透過添加 'use cache'、將存取移到 Suspense 邊界內,或標記為請求時取得來修正。
工作流程 B:升級 Next.js(自由度低)
- [ ] 閱讀 references/versions.md 的「舊模式」與安全下限
- [ ] 提交一個乾淨的樹;建立一個分支
- [ ] 執行官方升級工具:`npx next@canary upgrade --agent=latest`
(如果代理流程不可用,則使用 `npx @next/codemod@canary upgrade latest`)
- [ ] 同時升級 react、react-dom 和 @types/react 以及 next
- [ ] 移除 `runtime = 'edge'` 匯出;將 middleware.ts 重新命名為 proxy.ts(Node 執行環境)
- [ ] 執行驗證迴圈;然後手動進行冒煙測試,檢查驗證、重定向、快取和重新驗證
安全優先:如果已安裝的版本低於 versions.md 中的修補下限,請升級 next 本身(僅修補 React 套件是不夠的)。
工作流程 C:在現有應用程式中採用 Cache Components
逐個路由遷移。在一個分支上啟用 cacheComponents(在 16.4+ 上加上 partialPrefetching),執行 next build,然後修正每個報告的邊界。請參閱 references/caching.md。如果已安裝,Next.js 的 next-cache-components-adoption 技能會深入涵蓋機制;請與本技能一起使用。
驗證與安全規則
- 在 DAL 以及每個伺服器操作和路由處理器中進行授權。代理/中介軟體檢查僅作為樂觀的重新導向。CVE-2025-29927 顯示,基於標頭的中介軟體繞過是可能的。
- 伺服器操作是公開的 HTTP 端點:驗證輸入、檢查 session、檢查所有權。
- 在包含祕密或資料庫存取的模組中匯入
server-only;向客戶端元件返回 DTO(僅包含必要欄位)。 - 詳細資訊:
references/data-and-auth.md。
根據設計稿或模型實作
- 盤點設計:代碼(顏色、字體比例、間距、圓角)、元件、狀態(懸停、焦點、禁用、載入、空、錯誤)和斷點。
- 首先映射到專案現有的代碼和元件;將新代碼添加到主題中,而不是作為一次性值。
- 先建構靜態的伺服器元件標記,然後在葉節點添加互動性。
- 檢查 320px、平板和桌面寬度。檢查鍵盤和螢幕閱讀器標籤。尊重
prefers-reduced-motion。 - 如果有瀏覽器工具或 Playwright 可用,截圖並與設計稿比較;迭代直到間距和排版匹配。
審查模式
使用 references/review-checklist.md。將每個發現報告為 阻塞 / 應修復 / 小問題,並附上 file:line、問題說明以及具體的程式碼修正。按嚴重程度排序發現。阻塞項包括:僅在代理中進行授權、祕密洩漏到客戶端套件、未驗證的伺服器操作輸入、有漏洞的 next 版本,以及共享的 'use cache' 範圍內的特定使用者資料。
參考文件對照表
references/versions.md:版本、安全下限、舊模式、驗證注意事項references/data-and-auth.md:DAL 模式、伺服器操作範本、session 處理references/caching.md:Cache Components 規則、ensureStatic、navigation()/prefetch()references/review-checklist.md:按影響力排序的規則