部署
恭喜你,现在是时候发布到生产环境了。
你可以部署使用 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"
脚本
{
"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)时,或者在任何云提供商的容器内运行时,你可以使用此方法。
- 在你的机器上安装 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 的逻辑(或使用外部包),你或许可以将此逻辑移动到布局作为服务器组件。例如,检查 headers 和 重定向。你还可以使用 headers、cookies 或查询参数通过 next.config.js
重定向 或 重写。如果这不起作用,你也可以使用自定义服务器。
环境变量
Next.js 可以同时支持构建时和运行时环境变量。
默认情况下,环境变量仅在服务器上可用。要将环境变量暴露给浏览器,它必须以 NEXT_PUBLIC_
为前缀。但是,这些公共环境变量将在 next build
期间内联到 JavaScript 包中。
要读取运行时环境变量,我们建议使用 getServerSideProps
或逐步采用 App Router。
这允许你使用单个 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: <在 getStaticProps 中的 revalidate>, 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
配置。当检索 JavaScript 或 CSS 文件时,Next.js 将使用此前缀。将你的资源分离到不同的域确实会带来在 DNS 和 TLS 解析上花费额外时间的缺点。
配置缓存
默认情况下,生成的缓存资源将存储在内存(默认为 50mb)和磁盘上。如果你正在使用容器编排平台(如 Kubernetes)托管 Next.js,则每个 pod 都将拥有缓存的副本。为了防止由于默认情况下 pod 之间不共享缓存而显示过时的数据,你可以配置 Next.js 缓存以提供缓存处理程序并禁用内存缓存。
要在自托管时配置 ISR/数据缓存位置,你可以在 next.config.js
文件中配置自定义处理程序
module.exports = {
cacheHandler: require.resolve('./cache-handler.js'),
cacheMaxMemorySize: 0, // disable default in-memory caching
}
然后,在你的项目根目录中创建 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.includes(tag))) {
cache.delete(key)
}
}
}
// If you want to have temporary in memory cache for a single request that is reset
// before the next request you can leverage this method
resetRequestCache() {}
}
使用自定义缓存处理程序将允许你确保托管你的 Next.js 应用程序的所有 pod 之间的一致性。例如,你可以将缓存的值保存在任何地方,例如 Redis 或 AWS S3。
须知
revalidatePath
是缓存标签之上的便利层。调用revalidatePath
将使用提供的页面的特殊默认标签调用revalidateTag
函数。
构建缓存
Next.js 在 next build
期间生成一个 ID,以标识正在提供的应用程序的版本。应使用相同的构建并启动多个容器。
如果你要为环境的每个阶段重建,你将需要生成一个一致的构建 ID 以在容器之间使用。在 next.config.js
中使用 generateBuildId
命令
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
标头。
手动优雅关闭
当自托管时,您可能希望在服务器因 SIGTERM
或 SIGINT
信号而关闭时运行代码。
您可以将环境变量 NEXT_MANUAL_SIG_HANDLE
设置为 true
,然后在您的 _document.js
文件中注册该信号的处理程序。您将需要直接在 package.json
脚本中注册环境变量,而不是在 .env
文件中。
须知:手动信号处理在
next dev
中不可用。
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "NEXT_MANUAL_SIG_HANDLE=true next start"
}
}
if (process.env.NEXT_MANUAL_SIG_HANDLE) {
process.on('SIGTERM', () => {
console.log('Received SIGTERM: cleaning up')
process.exit(0)
})
process.on('SIGINT', () => {
console.log('Received SIGINT: cleaning up')
process.exit(0)
})
}
生产环境清单
静态导出
多区域
持续集成 (CI) 构建缓存
这有帮助吗?