部署
恭喜,现在是时候将您的应用发布到生产环境了。
您可以部署 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 的逻辑(或使用外部包),您可能能够将此逻辑作为 服务器组件 移动到 布局 中。例如,检查 标头 和 重定向。您还可以使用标头、cookie 或查询参数通过 重定向 或 重写 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: <revalidate in getStaticProps>, stale-while-revalidate
。此重新验证时间以秒为单位定义在您的getStaticProps
函数 中。如果您设置revalidate: false
,它将默认为一年缓存持续时间。 - 动态渲染的页面会设置一个
Cache-Control
头为private, no-cache, no-store, max-age=0, must-revalidate
以防止用户特定数据被缓存。这适用于 App 路由器和 Pages 路由器。这也包括 草稿模式。
静态资源
如果您想将静态资源托管在不同的域名或 CDN 上,您可以使用 next.config.js
中的 assetPrefix
配置。Next.js 会在检索 JavaScript 或 CSS 文件时使用此资源前缀。将您的资源分离到不同的域名确实会带来额外 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.include(tag))) {
cache.delete(key)
}
}
}
}
使用自定义缓存处理程序,您可以确保托管 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) 构建缓存
这是否有帮助?