跳到内容

output

在构建过程中,Next.js 会自动追踪每个页面及其依赖项,以确定部署应用程序生产版本所需的所有文件。

此功能有助于大幅减小部署大小。以前,使用 Docker 进行部署时,您需要安装 package 的所有 `dependencies` 文件才能运行 `next start`。从 Next.js 12 开始,您可以利用 `.next/` 目录中的输出文件追踪来仅包含必要的文件。

此外,这消除了对已弃用的 `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

须知:

  • `next.config.js` 在 `next build` 期间读取并序列化到 `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` 与 include 结合使用。

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

须知:

  • 为实现跨平台兼容性,在模式中优先使用正斜杠(`/`)。
  • 尽可能缩小模式范围,以避免过大的跟踪文件(避免在仓库根目录使用 `**/*`)。

本机/运行时资产的常见包含模式。

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