跳到內容

output

在構建過程中,Next.js 會自動追蹤每個頁面及其依賴項,以確定部署應用程式生產版本所需的所有檔案。

此功能有助於大幅減小部署大小。以前,使用 Docker 部署時,您需要安裝包的 `dependencies` 中的所有檔案才能執行 `next start`。從 Next.js 12 開始,您可以利用 `.next/` 目錄中的輸出檔案追蹤(Output File Tracing)來僅包含必要的檔案。

此外,這消除了對已棄用的 `serverless` 目標的需要,該目標可能導致各種問題併產生不必要的重複。

工作原理

在 `next build` 期間,Next.js 將使用 `@vercel/nft` 靜態分析 `import`、`require` 和 `fs` 用法,以確定頁面可能載入的所有檔案。

Next.js 的生產伺服器也對其所需檔案進行了追蹤,並輸出到 `.next/next-server.js.nft.json`,這可以在生產中使用。

要利用輸出到 `.next` 輸出目錄的 `.nft.json` 檔案,您可以讀取每個追蹤中相對於 `.nft.json` 檔案的檔案列表,然後將其複製到部署位置。

自動複製追蹤檔案

Next.js 可以自動建立一個 `standalone` 資料夾,該資料夾僅複製生產部署所需的檔案,包括 `node_modules` 中的選定檔案。

要在 `next.config.js` 中啟用此自動複製功能。

next.config.js
module.exports = {
  output: 'standalone',
}

這將在 `.next/standalone` 處建立一個資料夾,然後可以單獨部署,而無需安裝 `node_modules`。

此外,還會輸出一個最小的 `server.js` 檔案,可以代替 `next start` 使用。預設情況下,此最小伺服器不會複製 `public` 或 `.next/static` 資料夾,因為這些資料夾理想情況下應由 CDN 處理,儘管這些資料夾可以手動複製到 `standalone/public` 和 `standalone/.next/static` 資料夾,之後 `server.js` 檔案將自動提供這些檔案。

要手動複製這些檔案,您可以在 `next build` 之後使用 `cp` 命令列工具

終端
cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/

要在本地啟動您的最小 `server.js` 檔案,請執行以下命令

終端
node .next/standalone/server.js

須知:

  • 如果您的專案需要監聽特定埠或主機名,您可以在執行 `server.js` 之前定義 `PORT` 或 `HOSTNAME` 環境變數。例如,執行 `PORT=8080 HOSTNAME=0.0.0.0 node server.js` 以在 `http://0.0.0.0:8080` 上啟動伺服器。

注意事項

  • 在 monorepo 設定中進行追蹤時,專案目錄預設用於追蹤。對於 `next build packages/web-app`,`packages/web-app` 將是追蹤根目錄,此資料夾之外的任何檔案都不會被包含。要包含此資料夾之外的檔案,您可以在 `next.config.js` 中設定 `outputFileTracingRoot`。
packages/web-app/next.config.js
const path = require('path')
 
module.exports = {
  // this includes files from the monorepo base two directories up
  outputFileTracingRoot: path.join(__dirname, '../../'),
}
  • 在某些情況下,Next.js 可能無法包含所需檔案,或者可能錯誤地包含未使用檔案。在這些情況下,您可以在 `next.config.js` 中分別利用 `outputFileTracingExcludes` 和 `outputFileTracingIncludes`。每個選項都接受一個物件,其鍵是**路由 glob**(使用 picomatch 匹配路由路徑,例如 `'/api/hello'`),其值是**從專案根目錄解析的 glob 模式**,用於指定在追蹤中包含或排除的檔案。

須知:在 monorepo 中,`project root` 指的是 Next.js 專案根目錄(包含 next.config.js 的資料夾,例如 packages/web-app),不一定是 monorepo 根目錄。

next.config.js
module.exports = {
  outputFileTracingExcludes: {
    '/api/hello': ['./un-necessary-folder/**/*'],
  },
  outputFileTracingIncludes: {
    '/api/another': ['./necessary-folder/**/*'],
    '/api/login/\\[\\[\\.\\.\\.slug\\]\\]': [
      './node_modules/aws-crt/dist/bin/**/*',
    ],
  },
}

使用 `src/` 目錄不會改變您編寫這些選項的方式

  • 仍然匹配路由路徑(`'/api/hello'`、`'/products/[id]'` 等)。
  • 可以引用 `src/` 下的路徑,因為它們是相對於專案根目錄解析的。
next.config.js
module.exports = {
  outputFileTracingIncludes: {
    '/products/*': ['src/lib/payments/**/*'],
    '/*': ['src/config/runtime/**/*.json'],
  },
  outputFileTracingExcludes: {
    '/api/*': ['src/temp/**/*', 'public/large-logs/**/*'],
  },
}

您還可以使用全域性鍵(如 `'/*'`)定位所有路由

next.config.js
module.exports = {
  outputFileTracingIncludes: {
    '/*': ['src/i18n/locales/**/*.json'],
  },
}

這些選項應用於伺服器追蹤,不影響不生成伺服器追蹤檔案的路由

  • Edge Runtime 路由不受影響。
  • 完全靜態頁面不受影響。

在 monorepo 中,或者當您需要包含應用程式資料夾之外的檔案時,將 `outputFileTracingRoot` 與包含項結合使用

next.config.js
const path = require('path')
 
module.exports = {
  // Trace from the monorepo root
  outputFileTracingRoot: path.join(__dirname, '../../'),
  outputFileTracingIncludes: {
    '/route1': ['../shared/assets/**/*'],
  },
}

須知:

  • 模式中首選正斜槓(`/`)以實現跨平臺相容性。
  • 儘量縮小模式範圍以避免過大的追蹤(避免在 repo 根目錄使用 `**/*`)。

用於原生/執行時資產的常見包含模式

next.config.js
module.exports = {
  outputFileTracingIncludes: {
    '/*': ['node_modules/sharp/**/*', 'node_modules/aws-crt/dist/bin/**/*'],
  },
}