部署
恭喜你,是时候部署到生产环境了。
你可以选择 使用 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:
Node.js 服务器
Next.js 可以部署到任何支持 Node.js 的托管提供商。确保你的 package.json
有 "build"
和 "start"
脚本:
然后,运行 npm run build
来构建你的应用。最后,运行 npm run start
来启动 Node.js 服务器。这个服务器支持所有 Next.js 功能。
Docker 镜像
Next.js 可以部署到任何支持 Docker 容器的托管提供商。当部署到像 Kubernetes 这样的容器编排器时,或在任何云提供商的容器中运行时,你可以使用这种方法。
- 在你的机器上 安装 Docker
- 克隆我们的示例 (或 多环境示例)
- 构建你的容器:
docker build -t nextjs-docker .
- 运行你的容器:
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
中定义自定义图像加载器来与 静态导出 一起使用。请注意,图像是在运行时优化的,而不是在构建期间。
值得注意的是:
中间件
中间件 在使用 next start
部署时可以零配置自托管。由于它需要访问传入的请求,因此在使用 静态导出 时不支持。
中间件使用一个 运行时,该运行时是所有可用 Node.js API 的子集,以帮助确保低延迟,因为它可能在应用的每个路由或资源之前运行。这个运行时不需要在 "边缘" 运行,并且可以在单区域服务器中工作。要在多个区域运行中间件,需要额外的配置和基础设施。
如果你想添加需要所有 Node.js API 的逻辑 (或使用外部包),你可能可以将这个逻辑移动到 布局 中作为 服务器组件。例如,检查 头部信息 和 重定向。你还可以使用头部信息、cookie 或查询参数通过 next.config.js
进行 重定向 或 重写。如果这些方法都不适用,你还可以使用 自定义服务器。
环境变量
Next.js 可以支持构建时和运行时环境变量。
默认情况下,环境变量只在服务器上可用。要将环境变量暴露给浏览器,必须以 NEXT_PUBLIC_
为前缀。然而,这些公共环境变量在 next build
期间会被内联到 JavaScript 包中。
要读取运行时环境变量,我们建议使用 getServerSideProps
或 逐步采用 App Router。使用 App Router,我们可以在动态渲染期间安全地在服务器上读取环境变量。这允许你使用单个 Docker 镜像,可以在具有不同值的多个环境中部署。
值得注意的是:
- 你可以使用
register
函数 在服务器启动时运行代码。- 我们不推荐使用 runtimeConfig 选项,因为它不适用于独立输出模式。相反,我们建议 逐步采用 App Router。
缓存和 ISR
Next.js 可以缓存响应、生成的静态页面、构建输出和其他静态资源如图像、字体和脚本。
缓存和重新验证页面 (使用增量静态再生成 (ISR) 或 App Router 中的较新函数) 使用 相同的共享缓存。默认情况下,这个缓存存储在你的 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 Router 和 Pages Router。这也包括 草稿模式。
静态资源
如果你想在不同的域名或 CDN 上托管静态资源,你可以在 next.config.js
中使用 assetPrefix
配置。Next.js 在检索 JavaScript 或 CSS 文件时会使用这个资源前缀。将你的资源分离到不同的域名确实会带来 DNS 和 TLS 解析额外时间的缺点。
配置缓存
默认情况下,生成的缓存资源将存储在内存中 (默认为 50mb) 和磁盘上。如果你使用像 Kubernetes 这样的容器编排平台托管 Next.js,每个 pod 将有一个缓存副本。为了防止由于缓存默认不在 pod 之间共享而显示过时数据,你可以配置 Next.js 缓存以提供一个缓存处理程序并禁用内存缓存。
要在自托管时配置 ISR/数据缓存位置,你可以在 next.config.js
文件中配置一个自定义处理程序:
然后,在你的项目根目录创建 cache-handler.js
,例如:
使用自定义缓存处理程序可以确保托管你的 Next.js 应用的所有 pod 之间的一致性。例如,你可以将缓存的值保存在任何地方,比如 Redis 或 AWS S3。
值得注意的是:
revalidatePath
是缓存标签的一个便捷层。调用revalidatePath
将为提供的页面调用revalidateTag
函数,使用一个特殊的默认标签。
构建缓存
Next.js 在 next build
期间生成一个 ID 来识别正在提供的应用版本。相同的构建应该被用于启动多个容器。
如果你为环境的每个阶段重新构建,你需要生成一个一致的构建 ID 在容器之间使用。在 next.config.js
中使用 generateBuildId
命令:
版本偏差
Next.js 会自动缓解大多数 版本偏差 的实例,并在检测到时自动重新加载应用以获取新资源。例如,如果 deploymentId
不匹配,页面之间的转换将执行硬导航,而不是使用预取的值。
当应用重新加载时,如果它没有设计成在页面导航之间持久化,可能会丢失应用状态。例如,使用 URL 状态或本地存储会在页面刷新后保持状态。然而,像 useState
这样的组件状态在这种导航中会丢失。
Vercel 为 Next.js 应用提供额外的 偏差保护,以确保即使在新版本部署后,旧客户端仍然可以访问前一版本的资源和函数。
你可以在 next.config.js
文件中手动配置 deploymentId
属性,以确保每个请求使用 ?dpl
查询字符串或 x-deployment-id
头。
流式传输和 Suspense
Next.js App Router 在自托管时支持 流式响应。如果你使用 Nginx 或类似的代理,你需要配置它以禁用缓冲以启用流式传输。
例如,你可以通过将 X-Accel-Buffering
设置为 no
来在 Nginx 中禁用缓冲: