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` 中啟用此自動複製功能。
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`。
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 根目錄。
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/` 下的路徑,因為它們是相對於專案根目錄解析的。
module.exports = {
outputFileTracingIncludes: {
'/products/*': ['src/lib/payments/**/*'],
'/*': ['src/config/runtime/**/*.json'],
},
outputFileTracingExcludes: {
'/api/*': ['src/temp/**/*', 'public/large-logs/**/*'],
},
}您還可以使用全域性鍵(如 `'/*'`)定位所有路由
module.exports = {
outputFileTracingIncludes: {
'/*': ['src/i18n/locales/**/*.json'],
},
}這些選項應用於伺服器追蹤,不影響不生成伺服器追蹤檔案的路由
- Edge Runtime 路由不受影響。
- 完全靜態頁面不受影響。
在 monorepo 中,或者當您需要包含應用程式資料夾之外的檔案時,將 `outputFileTracingRoot` 與包含項結合使用
const path = require('path')
module.exports = {
// Trace from the monorepo root
outputFileTracingRoot: path.join(__dirname, '../../'),
outputFileTracingIncludes: {
'/route1': ['../shared/assets/**/*'],
},
}須知:
- 模式中首選正斜槓(`/`)以實現跨平臺相容性。
- 儘量縮小模式範圍以避免過大的追蹤(避免在 repo 根目錄使用 `**/*`)。
用於原生/執行時資產的常見包含模式
module.exports = {
outputFileTracingIncludes: {
'/*': ['node_modules/sharp/**/*', 'node_modules/aws-crt/dist/bin/**/*'],
},
}這有幫助嗎?