跳至内容

部署

恭喜,现在是时候发布到生产环境了。

您可以部署使用 Vercel 托管的 Next.js,或在 Node.js 服务器、Docker 镜像甚至静态 HTML 文件上进行自托管。使用 `next start` 部署时,支持所有 Next.js 功能。

生产构建

运行 `next build` 会生成应用程序的优化版本以供生产使用。HTML、CSS 和 JavaScript 文件是根据您的页面创建的。JavaScript 会被**编译**,并且浏览器捆绑包会使用Next.js 编译器进行**压缩**,以帮助实现最佳性能并支持所有现代浏览器

Next.js 生成托管和自托管 Next.js 使用的标准部署输出。这确保了两种部署方法都支持所有功能。在下一个主要版本中,我们将把此输出转换为我们的构建输出 API 规范

使用 Vercel 托管的 Next.js

Vercel,Next.js 的创建者和维护者,为您的 Next.js 应用程序提供托管基础设施和开发者体验平台。

部署到 Vercel 是零配置的,并提供额外的增强功能,以实现全球范围内的可扩展性、可用性和性能。但是,即使自托管,所有 Next.js 功能仍然受支持。

了解有关Vercel 上的 Next.js免费部署模板的更多信息,以试用它。

自托管

您可以通过三种不同的方式自托管 Next.js

🎥 观看: 了解更多关于自托管 Next.js 的信息 → YouTube (45 分钟)

Node.js 服务器

Next.js 可以部署到任何支持 Node.js 的托管服务提供商。确保您的 package.json 文件包含 "build""start" 脚本

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

然后,运行 npm run build 来构建您的应用程序。最后,运行 npm run start 启动 Node.js 服务器。此服务器支持所有 Next.js 功能。

Docker 镜像

Next.js 可以部署到任何支持 Docker 容器的托管服务提供商。当部署到容器编排器(例如 Kubernetes)或在任何云提供商的容器中运行时,您可以使用此方法。

  1. 在您的机器上安装 Docker
  2. 克隆我们的示例(或 多环境示例
  3. 构建您的容器:docker build -t nextjs-docker .
  4. 运行您的容器:docker run -p 3000:3000 nextjs-docker

通过 Docker 使用 Next.js 支持所有 Next.js 功能。

静态 HTML 导出

Next.js 可以作为静态站点或单页应用程序 (SPA) 启动,然后可以选择升级以使用需要服务器的功能。

由于 Next.js 支持此 静态导出,因此它可以部署和托管在任何可以提供 HTML/CSS/JS 静态资源的 Web 服务器上。这包括 AWS S3、Nginx 或 Apache 等工具。

静态导出 的方式运行不支持需要服务器的 Next.js 功能。了解更多

值得注意

功能

图像优化

图像优化 通过 next/image 在使用 next start 部署时无需任何配置即可自托管。如果您希望使用单独的服务来优化图像,则可以 配置图像加载器

通过在 next.config.js 中定义自定义图像加载器,图像优化可以与 静态导出 一起使用。请注意,图像是在运行时优化的,而不是在构建期间优化的。

值得注意

  • 在基于 glibc 的 Linux 系统上,图像优化可能需要 其他配置 以防止过度使用内存。
  • 了解更多关于 优化图像的缓存行为 以及如何配置 TTL。
  • 您还可以 禁用图像优化 并保留使用 next/image 的其他好处(如果您愿意)。例如,如果您自己单独优化图像。

中间件

中间件 在使用 next start 部署时无需任何配置即可自托管。由于它需要访问传入的请求,因此在使用 静态导出 时不受支持。

中间件使用 运行时,它是所有可用 Node.js API 的子集,有助于确保低延迟,因为它可能在应用程序中的每个路由或资源之前运行。此运行时不需要“在边缘”运行,并且可以在单个区域的服务器中运行。要在多个区域运行中间件,需要额外的配置和基础设施。

如果您希望添加需要所有 Node.js API 的逻辑(或使用外部包),则可以将此逻辑移动到 布局 作为 服务器组件。例如,检查 标头重定向。您还可以使用标头、cookie 或查询参数来 重定向重写 通过 next.config.js。如果这不起作用,您还可以使用 自定义服务器

环境变量

Next.js 可以支持构建时和运行时环境变量。

默认情况下,环境变量仅在服务器上可用。要将环境变量公开给浏览器,必须以 NEXT_PUBLIC_ 为前缀。但是,这些公共环境变量将在 next build 期间内联到 JavaScript 包中。

您可以在动态渲染期间安全地在服务器上读取环境变量。

app/page.ts
import { connection } from 'next/server'
 
export default async function Component() {
  await connection()
  // cookies, headers, and other Dynamic APIs
  // will also opt into dynamic rendering, meaning
  // this env variable is evaluated at runtime
  const value = process.env.MY_VALUE
  // ...
}

这允许您使用单个 Docker 镜像,该镜像可以通过具有不同值的多个环境进行提升。

值得注意

  • 您可以使用 register 函数 在服务器启动时运行代码。
  • 我们不建议使用 runtimeConfig 选项,因为这与独立输出模式不兼容。相反,我们建议 逐步采用 App Router。

缓存和 ISR

Next.js 可以缓存响应、生成的静态页面、构建输出以及其他静态资源(如图像、字体和脚本)。

缓存和重新验证页面(使用 增量静态再生)使用**相同的共享缓存**。默认情况下,此缓存存储在 Next.js 服务器上的文件系统(磁盘)中。**在使用 Pages 和 App Router 自托管时,此功能会自动生效**。

如果您希望将缓存的页面和数据持久化到持久性存储中,或在 Next.js 应用程序的多个容器或实例之间共享缓存,则可以配置 Next.js 缓存位置。

自动缓存

  • Next.js 将 Cache-Control 标头设置为 public, max-age=31536000, immutable,以实现真正的不可变资产。它不可覆盖。这些不可变文件在文件名中包含 SHA 哈希,因此可以无限期安全地缓存。例如,静态图像导入。您可以 配置图像的 TTL
  • 增量静态再生 (ISR) 会设置 Cache-Control 头为 s-maxage: <revalidate in getStaticProps>, stale-while-revalidate。此重新验证时间以秒为单位,在您的 getStaticProps 函数 中定义。如果您设置 revalidate: false,则默认为一年缓存时长。
  • 动态渲染的页面会设置 Cache-Control 头为 private, no-cache, no-store, max-age=0, must-revalidate,以防止缓存用户特定数据。这适用于 App 路由器和页面路由器。这也包括 草稿模式

静态资源

如果您想将静态资源托管在不同的域名或 CDN 上,您可以使用 next.config.js 中的 assetPrefix 配置。Next.js 会在检索 JavaScript 或 CSS 文件时使用此资源前缀。将您的资源分离到不同的域名确实会带来额外的 DNS 和 TLS 解析时间。

了解更多关于 assetPrefix 的信息.

配置缓存

默认情况下,生成的缓存资产将存储在内存中(默认为 50mb)和磁盘上。如果您使用 Kubernetes 等容器编排平台托管 Next.js,则每个 Pod 都将拥有缓存的副本。为了防止显示过时数据(因为缓存默认情况下不会在 Pod 之间共享),您可以配置 Next.js 缓存以提供缓存处理程序并禁用内存缓存。

要在自托管时配置 ISR/数据缓存位置,您可以在 next.config.js 文件中配置自定义处理程序。

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
}

然后,在项目的根目录下创建 cache-handler.js,例如

cache-handler.js
const cache = new Map()
 
module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }
 
  async get(key) {
    // This could be stored anywhere, like durable storage
    return cache.get(key)
  }
 
  async set(key, data, ctx) {
    // This could be stored anywhere, like durable storage
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }
 
  async revalidateTag(tags) {
    // tags is either a string or an array of strings
    tags = [tags].flat()
    // Iterate over all entries in the cache
    for (let [key, value] of cache) {
      // If the value's tags include the specified tag, delete this entry
      if (value.tags.some((tag) => tags.include(tag))) {
        cache.delete(key)
      }
    }
  }
}

使用自定义缓存处理程序,您可以确保托管 Next.js 应用程序的所有 Pod 之间的一致性。例如,您可以将缓存值保存在任何地方,例如 Redis 或 AWS S3。

值得注意

  • revalidatePath 是缓存标签之上的一个便利层。调用 revalidatePath 将使用提供的页面的特殊默认标签调用 revalidateTag 函数。

构建缓存

Next.js 在 next build 期间生成一个 ID 来识别正在提供服务的应用程序版本。应使用相同的构建并启动多个容器。

如果您正在为环境的每个阶段重建,则需要生成一个一致的构建 ID 以在容器之间使用。在 next.config.js 中使用 generateBuildId 命令。

next.config.js
module.exports = {
  generateBuildId: async () => {
    // This could be anything, using the latest git hash
    return process.env.GIT_HASH
  },
}

版本偏差

Next.js 会自动缓解大多数 版本偏差 实例,并在检测到时自动重新加载应用程序以检索新资源。例如,如果 deploymentId 不匹配,则页面之间的转换将执行硬导航,而不是使用预取的值。

重新加载应用程序时,如果应用程序状态没有设计为在页面导航之间持久化,则可能会丢失应用程序状态。例如,使用 URL 状态或本地存储将在页面刷新后持久化状态。但是,诸如 useState 之类的组件状态将在此类导航中丢失。

Vercel 为 Next.js 应用程序提供了额外的 偏差保护,以确保即使在新版本部署后,旧客户端仍然可以使用先前版本中的资源和函数。

您可以手动配置 next.config.js 文件中的 deploymentId 属性,以确保每个请求都使用 ?dpl 查询字符串或 x-deployment-id 标头。

流和 Suspense

Next.js App 路由器在自托管时支持 流式响应。如果您使用 Nginx 或类似的代理,则需要将其配置为禁用缓冲以启用流式传输。

例如,您可以通过将 X-Accel-Buffering 设置为 no 来禁用 Nginx 中的缓冲。

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*{/}?',
        headers: [
          {
            key: 'X-Accel-Buffering',
            value: 'no',
          },
        ],
      },
    ]
  },
}

部分预渲染

部分预渲染(实验性) 默认情况下与 Next.js 一起使用,而不是 CDN 功能。这包括作为 Node.js 服务器(通过 next start)部署以及与 Docker 容器一起使用时。

与 CDN 一起使用

当在 Next.js 应用程序前面使用 CDN 时,当访问动态 API 时,页面将包含 Cache-Control: private 响应头。这确保生成的 HTML 页面被标记为不可缓存。如果页面完全预渲染为静态,则它将包含 Cache-Control: public 以允许页面在 CDN 上缓存。

如果您不需要混合使用静态和动态组件,您可以将整个路由设为静态并在 CDN 上缓存输出的 HTML。当不使用动态 API 时,运行 next build 时的默认行为是此自动静态优化。