Communitygithub.com

Nuvraxis/nuvraxis-plugins

適用於 Nuvraxis 開發的 Next.js 16 App Router 應用程式之生產規則:涵蓋伺服器/用戶端元件邊界、快取元件(使用「use cache」、cacheLife、cacheTag、updateTag)、伺服器動作、路由處理器、環境變數處理、儀器化、獨立輸出與 /api/health 路由。當專案的 package.json 包含「next」、存在 app/ 或 src/app/ 目錄、next.config.ts、proxy.ts、instrumentation.ts 或名為 page.tsx、layout.tsx、route.ts、loading.tsx、error.tsx 的檔案時使用。

nuvraxis-plugins 是什麼?

這項技能為使用 Next.js 16 App Router 的 Nuvraxis 專案提供了生產環境的嚴格規則。它不僅強化了伺服器元件優先的原則,明確要求「use client」指令僅用於需要狀態、效果或瀏覽器 API 的最小葉元件,還深入規範了 React 19.3 與 Turbopack 預設設定下的新式「Cache Components」機制——要求開發者明確使用「use cache」搭配 cacheLife 與 cacheTag 來控制快取,並以 updateTag 在伺服器動作中實現讀取自身寫入的一致性,避免了舊版設定(如 export const dynamic)的衝突。專為 Nuvraxis 團隊量身打造,這項技能特別依賴其提供的 valibot 驗證模式,從伺服器動作的輸入驗證與授權檢查、路由處理器的外部用戶端導向,到環境變數的嚴格區分(NEXT_PUBLIC_ 僅用於建置時常量,其餘伺服器端執行期變數通過 src/env.ts 統一驗證),確保所有程式碼在一致性與安全性上達到最高標準。此外,它還規定了所有應用程式必須包含動態且無依賴的 /api/health 端點(避免由慢速資料庫造成容器重啟),以及 error.tsx、loading.tsx、not-found.tsx 的適當佈署,並要求所有訪問請求時間數據(如 cookies()、headers()、searchParams)必須包裹在 Suspense 邊界內以避免預渲染失敗。這項技能支援 Claude Code 與其他 AI 代理,與 next-best-practices 及 nextjs-security 技能互補,專注於 Nuvraxis 特有的建置與部署慣例。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Nuvraxis/nuvraxis-plugins/tree/HEAD/plugins/nuvraxis-frontend/skills/nextjs-production

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Next.js 在生產環境

適用於任何 Next.js 16 App Router 應用程式中的程式碼。安全性相關規則(actions 中的驗證、CSP、標頭、taint)在 nextjs-security 中;容器規則在 docker-nextjs 中。Claude Code 內建的 next-best-practices 技能涵蓋了一般檔案慣例、metadata、圖片和字型優化的詳細內容;此技能僅補充我們建置和發佈時的特定內容。

基準:Next 16.4、React 19.3、Turbopack(dev 和 build 的預設值)、cacheComponents: true 搭配 partialPrefetching: true、output: "standalone"、typedRoutes: true。範本的 next.config.ts 是唯一真相來源。

規則

  1. 預設使用伺服器元件;僅在需要狀態、效果、瀏覽器 API 或事件處理常式時才使用 "use client"。 將指令放在需要它的最小葉子元件上。不要因為檔案匯入 nuvui 就添加它:nuvui 的狀態相關部分會自帶指令(請參閱 nuvui 技能中的 rules/server-components.md)。

    // 錯誤:因為一個處理常式導致整個頁面變成客戶端元件
    "use client";
    export default function Page() { … <Select onValueChange={…} /> … }
    
    // 正確:頁面保留在伺服器端,處理常式位於葉子元件中
    export default async function Page() {
      const people = await getPeople();
      return <PeopleFilter people={people} />; // people-filter.tsx 有 "use client"
    }
    

    傳入客戶端元件的 props 必須是可序列化的:不能有函式(Server Actions 除外),不能有類別實例。

  2. 在需要資料的伺服器元件上進行 fetch。 不要使用 useEffect 進行 fetch,不要為了提供資料給自己的頁面而使用路由處理常式。在同一個請求中使用 React 的 cache() 進行去重;跨請求的快取則使用規則 3。

  3. 使用 "use cache" + cacheLife + cacheTag 進行快取;其他所有內容都是動態的。 使用 Cache Components,除非你明確指定,否則沒有任何內容會被快取,且 fetch 沒有隱含快取。

    import { cacheLife, cacheTag } from "next/cache";
    
    export async function getInvoice(id: InvoiceId) {
      "use cache";
      cacheLife("minutes");
      cacheTag(`invoice:${id}`);
      return db.invoice.findUnique({ where: { id } });
    }
    

    不要使用舊的區段配置(export const dynamic、revalidate、fetchCache):在 Cache Components 下會報錯。引數和閉包捕獲的值會成為快取鍵的一部分,因此請傳遞 id,而不是整個請求物件。詳細資訊、設定檔和 "use cache: private":請參閱 references/caching.md。

  4. 在 Server Actions 中使用 updateTag 進行失效處理,在其他地方使用 revalidateTag(tag, "max")。 updateTag(tag) 提供「讀取自己寫入」的能力,且僅能在 Server Action 內部運作。從 webhook 或路由處理常式使用 revalidateTag(tag, "max")(stale-while-revalidate)或 revalidateTag(tag, { expire: 0 })。單一引數的 revalidateTag(tag) 已被棄用。

  5. 將請求時期的資料包裹在 <Suspense> 中,否則建置會失敗。 在 Suspense 邊界之外的 cookies()、headers()、searchParams、connection() 和未快取的 I/O 會阻止預先渲染,並顯示「在預先渲染期間使用了未快取或執行時期資料」。為其提供帶有骨架圖 fallback 的邊界、進行快取,或(僅限根佈局,請參閱規則 14)使用 export const instant = false 將路由標記為阻塞。所有 params、searchParams、cookies()、headers() 都是非同步的:請 await 它們。

  6. 每個 Server Action 都必須自行驗證其輸入和檢查授權。 Server Action 是一個公開的 POST 端點,無論它寫在哪個頁面上。使用 typescript-production 中的 schema(valibot)解析 FormData,然後進行授權檢查,接著執行變更,最後使用 updateTag。對於預期中的失敗,回傳一個類型標記的結果;僅在出現錯誤時才拋出例外。完整的規則集在 nextjs-security 中。

    "use server";
    export async function renameProject(_: State, form: FormData): Promise<State> {
      const session = await requireSession();                  // 如果不存在則回傳 401
      const input = v.safeParse(RenameProject, Object.fromEntries(form));
      if (!input.success) return { ok: false, errors: flatten(input.issues) };
      await assertCanEdit(session, input.output.projectId);    // 如果不允許則回傳 403
      await db.project.update(…);
      updateTag(`project:${input.output.projectId}`);
      return { ok: true };
    }
    
  7. 路由處理常式是為其他客戶端(webhooks、行動裝置、健康檢查)設計的,而不是為你自己的頁面。 將它們放在 app/api/ 下。像 action 一樣驗證請求主體,回傳 Response.json(...),並有目的地設定狀態碼。

  8. 每個應用程式都有 GET /api/health,動態且無依賴。 Docker HEALTHCHECK 和 Kubernetes 探針會呼叫它。它必須在不接觸資料庫的情況下回應,這樣一個慢速的依賴項就不會重新啟動每個 pod。await connection() 可防止它被預先渲染成靜態檔案。它位於範本中的 src/app/api/health/route.ts;proxy.ts 會從其匹配器中排除 /api/health。

  9. 在根目錄以及使用者體驗不同的每個區段中放置 error.tsx、loading.tsx 和 not-found.tsx。 error.tsx 是一個客戶端元件;透過 instrumentation.ts 的 onRequestError 記錄日誌,顯示一個帶有 reset 的重試按鈕,但絕不顯示錯誤訊息。對於找不到的記錄,應呼叫 notFound(),而不是渲染空白狀態。

  10. NEXT_PUBLIC_* 在建置時就已嵌入;其他所有內容都在執行時期於伺服器端讀取。 一個映像檔從 main 分支提升到生產環境時保持不變,因此 NEXT_PUBLIC_ 的值在所有環境中都相同。僅將建置時常量放在那裡(應用程式名稱、一個在所有環境中都相同的公開 Sentry DSN)。每個環境的配置(API URL、功能開關、機密)是伺服器端的 process.env.X,在 Server Component 或 action 中讀取,並在需要時作為 props 傳遞給客戶端。在 src/env.ts(valibot)中驗證 env 一次,然後從那裡匯入。不要在 next.config.ts 中使用 env 金鑰:它會被內聯到客戶端 bundle 中。

  11. 使用 import "server-only" 標記僅伺服器模組。 任何讀取機密、與資料庫通訊或匯入帶有憑證的 SDK 的模組。如果客戶端匯入它,建置將會失敗,而不是洩漏資訊。

  12. 使用 after() 處理不應延遲回應的工作(稽核日誌、分析、快取預熱)。在呼叫 after 之前讀取 cookies()/headers(),而不是在它內部。它在同一個行程中執行,因此 pod 需要其 SIGTERM 寬限期(圖表設定了 terminationGracePeriodSeconds)。

  13. 使用 src/instrumentation.ts 進行儀器化:registerOTel + onRequestError。 透過 @vercel/otel 的 OpenTelemetry,匯出器由執行時期的標準 OTEL_EXPORTER_OTLP_* 環境變數配置。請參閱 references/observability.md。

  14. 保留 output: "standalone",並且永遠不要從工作區外部匯入。 Docker runner 僅複製 .next/standalone、.next/static 和 public。在 monorepo 中,server.js 位於 .next/standalone/apps/<app>/server.js;工作區根目錄是從 pnpm-lock.yaml 中找到的,因此除非建置發出警告,否則不要設定 outputFileTracingRoot 或 turbopack.root。自有主機的詳細資訊(多副本、Server Action 金鑰、deploymentId):請參閱 references/self-hosting.md。

  15. 根佈局會讀取 CSP 隨機數,因此應用程式會根據每個請求進行渲染。 範本的 proxy.ts 設定了一個基於隨機數的 CSP,而 src/app/layout.tsx 有 export const instant = false。這是一個有意的權衡:隨機數和預先渲染的靜態 shell 無法共存,而對於需要登入的商業應用程式來說,嚴格的 CSP 勝出。使用 "use cache" 的資料快取仍然有效。在未閱讀 nextjs-security 規則 4 的情況下,不要移除任何一半。

  16. 樣式:全域 BEM SCSS,由元件匯入。 Turbopack 使用 sass 套件編譯 Sass;sassOptions.loadPaths: ["src/styles"] 使得 @use "abstracts" 可以從任何深度運作。不要使用 ~ 匯入,不要使用 sassOptions.functions。規則在 scss-bem 中。

  17. 圖片透過 next/image,字型透過 next/font。 sharp 隨 Next 一同提供,用作最佳化器;runner 映像檔不需要額外套件。遠端圖片需要帶有確切主機名稱的 images.remotePatterns。

  18. 使用 pnpm next analyze 檢查 bundle 大小(Turbopack 的分析器;@next/bundle-analyzer 僅支援 webpack)。使用 next/dynamic 對重型客戶端 widget(nuvui 編輯器、地圖、折疊線以下的圖表)進行延遲載入。

  19. 使用類型路由和生成的類型。 typedRoutes: true 會檢查 <Link href>;在 next typegen 之後(由 next dev/next build 自動執行),PageProps<"/invoices/[id]"> 和 LayoutProps 成為全域的。不要手寫 params 類型。

  20. 不要使用 next lint。 它在 16 版中被移除了。Biome 進行 lint(請參閱 biome);TypeScript 透過每個套件的 tsc --noEmit 進行檢查。

驗證

pnpm typecheck
pnpm lint
pnpm build                      # turbo run build: 在預先渲染錯誤、型別錯誤、Sass 錯誤時失敗
pnpm --filter <app> start &     # 然後:
curl -fsS localhost:3000/api/health

來源

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Nuvraxis/nuvraxis-plugins

>- Biome 2.5 setup and rules for Nuvraxis monorepos — root biome.json with pinned $schema, VCS ignore, formatter settings, the recommended preset with a11y and the react/next domains, nursery policy, organize imports, overrides, nested per-package configs ("extends": "//"), biome check --write locally, biome ci in CI, VS Code settings, and migrating from ESLint/Prettier. Use when the repo has biome.json or biome.jsonc, @biomejs/biome in package.json, .eslintrc*/eslint.config.*/.prettierrc* to migrate, or when fixing lint and formatting errors.

Nuvraxis/nuvraxis-plugins

>- Dockerfile rules for Next.js standalone apps in a pnpm + Turborepo monorepo — multi-stage build (turbo prune → pnpm fetch/offline install → turbo build → minimal runner), pinned Node 26 Alpine by digest, checksum-verified pnpm binary, non-root uid 1001, read-only root filesystem with a writable .next/cache, HEALTHCHECK on /api/health, build args only for NEXT_PUBLIC_* values, BuildKit secrets and cache mounts, multi-arch, OCI labels and .dockerignore. Use when the repo has a Dockerfile, .dockerignore, compose file, or next.config with output "standalone", or when asked to containerise, shrink, harden or debug an image.

Nuvraxis/nuvraxis-plugins

>- GitHub Actions conventions for Nuvraxis Next.js apps — exactly three workflows: pr.yaml (every PR to any branch: Biome, stylelint, typecheck/test/build with turbo --affected, Docker build + health check, helm lint + kubeconform; publishes nothing), main.yaml (push to main: one multi-arch image to GHCR tagged sha-SHORTSHA and main, provenance + SBOM, gha cache), release.yaml (tag vX.Y.Z: verify on main, retag the existing image without rebuilding, package and push the Helm chart to OCI, GitHub Release with chart, digest and SBOM). Minimal permissions per job, GITHUB_TOKEN only, pinned action majors. Use when editing .github/workflows/*, adding a CI step, or debugging a failed run or release.

Nuvraxis/nuvraxis-plugins

>- Helm chart rules for Nuvraxis Next.js apps — one chart per app in charts/ (named after the app), published to oci://ghcr.io/nuvraxis/charts and synced by Argo CD; Chart.yaml version/appVersion set only by release.yaml; Deployment with startup/liveness/readiness probes on /api/health, non-root read-only security context, emptyDir for .next/cache, ConfigMap + existing Secret via envFrom, Service, Ingress with cert-manager, HPA, PDB, ServiceAccount, topology spread; no Helm hooks; helm lint --strict + kubeconform. Use when the repo has charts/, Chart.yaml, values*.yaml, templates/*.yaml with Helm syntax, or an Argo CD Application, or when asked to deploy, scale, expose or configure the app on Kubernetes.

相關技能