部署
恭喜,您可以将应用程序部署到生产环境了。
您可以使用 Vercel 部署托管的 Next.js, 或在 Node.js 服务器、Docker 镜像,甚至静态 HTML 文件上自托管。使用next start部署时,所有 Next.js 功能都受支持。
生产构建
运行next build会为生产环境生成优化版本的应用程序。基于您的页面创建 HTML、CSS 和 JavaScript 文件。Next.js 编译器 compiledJavaScript 并 压缩 浏览器包,以帮助实现最佳性能并支持所有现代浏览器。
Next.js 生成一个标准的部署输出,可用于托管和自托管的 Next.js。这确保了所有功能在两种部署方法中都受支持。在下一个主要版本中,我们将把此输出转换为我们的构建输出 API 规范。
使用 Vercel 托管 Next.js
Vercel, Next.js 的创建者和维护者,您的 Next.js 应用程序提供托管基础设施和开发者体验平台。
部署到 Vercel 是零配置的,并提供了全球范围内的可扩展性、可用性和性能的额外增强。然而,所有 Next.js 功能在自托管时仍然受支持。
在 Vercel 上了解有关 Next.js 的更多信息或免费部署一个模板来试用。
自托管
您可以通过三种不同的方式自托管 Next.js:
Node.js Server
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 Image
Next.js 可以部署到任何支持Docker容器的托管提供商。在部署到 container orchestrators 时(例如 Kubernetes)或者在任何云提供商的容器内运行时可以使用此方法。
- 在您的机器上安装 Docker。
- 克隆我们的例子 (或者多环境的例子)
- 构建您的容器:
docker build -t nextjs-docker . - 运行您的容器:
docker run -p 3000:3000 nextjs-docker
Next.js 通过 Docker 支持所有的 Next.js 功能。
静态 HTML 导出
Next.js 允许您以静态站点或单页应用程序 (SPA) 开始,然后可以选择升级以使用需要服务器的功能。
因为 Next.js 支持静态导出, 它可以部署并托管在任何能够提供 HTML/CSS/JS 静态资源的 Web 服务器上。这包括 AWS S3、Nginx 或 Apache 等工具。
以静态导出运行不支持需要服务器的 Next.js 功能。了解更多。
您需要知道:
- 静态导出支持服务器组件。
特征
图像优化
在使用next start部署时,图像优化通过next/image进行自托管时无需任何配置。如果您希望有一个单独的服务来优化图像,您可以配置图像加载器。
图像优化可以通过在next.config.js中定义自定义图像加载器与静态导出一起使用。请注意,图像是在运行时而不是在构建时进行优化。
您需要知道:
Middleware
当使用next start部署,Middleware在自托管时无需配置即可工作。由于它需要访问传入的请求,因此在使用静态导出时不受支持。
Middleware 使用的运行时,它是所有可用 Node.js API 的子集,以帮助确保低延迟,因为它可能在您的应用程序中的每个路由或资源前运行。此运行时不需要在“边缘”运行,并且可以在单区域服务器中工作。要在多个区域运行 Middleware,需要额外的配置和基础设施。
如果您希望添加需要所有 Node.js API 的逻辑(或使用外部包), 您可以将此逻辑作为服务器组件移动到布局检查headers 和 redirecting。您还可以使用 headers、cookies 或查询参数通过next.config.js进行重定向 或 重写。如果这不起作用,您还可以使用自定义服务器。
环境变量
Next.js 支持构建时和运行时环境变量。
默认情况下,环境变量仅在服务器上可用。要将环境变量暴露给浏览器,必须以NEXT_PUBLIC_为前缀。然而,这些公共环境变量将在next build期间内联到 JavaScript 包中。
要读取运行时环境变量,我们建议使用getServerSideProps或逐步采用 App Router。使用 App Router,我们可以在动态渲染期间安全地在服务器上读取环境变量。这允许您使用单一的 Docker 镜像,并在多个环境中使用不同的值进行推广。
import { unstable_noStore as noStore } from 'next/cache';
export default function Component() {
noStore();
// cookies(), headers(), and other dynamic functions
// will also opt into dynamic rendering, making
// this env variable is evaluated at runtime
const value = process.env.MY_VALUE
...
}
您需要知道:
- 您可以使用
register函数在服务器启动时运行代码。- 我们不建议使用runtimeConfig选项,因为这不适用于独立输出模式。相反,我们建议逐步采用App Router。
缓存和 ISR
Next.js 可以缓存响应、生成的静态页面、构建输出以及其他静态资源,如图像、字体和脚本。
缓存和重新验证页面(使用 Incremental Static Regeneration (ISR)或 App Router 中的更新功能)使用相同的共享缓存。默认情况下,此缓存存储在您的 Next.js 服务器上的文件系统(磁盘)中。当使用 Pages 和 App Router 进行 自托管时,此功能会自动运行。
如果您想要将缓存的页面和数据保存到持久存储中,或 者在 Next.js 应用程序的多个容器或实例之间共享缓存,则可以配置 Next.js 缓存位置。
自动缓存
- Next.js 为真正不可变的资源设置
Cache-Controlheader 为public, max-age=31536000, immutable。此设置无法被覆盖。这些不可变文件的文件名中包含 SHA 哈希,因此可以安全地无限期缓存。例如静态图像导入。您可以为图像配置 TTL。 - Incremental Static Regeneration (ISR)将
Cache-Controlheader 设置为s-maxage: <revalidate in getStaticProps>, stale-while-revalidate。此重新验证时间在您的getStaticProps函数中以秒为单位定义。如果您设置revalidate: false,则默认缓存持续时间为一年。 - 动态渲染的页面将
Cache-Controlheader 设置为private, no-cache, no-store, max-age=0, must-revalidate以防止缓存用户特定的数据。这适用于 App Router 和 Pages Router。这也包括 Draft Mode。
静态资源
如果您希望在不同的域或 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(tag) {
// 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.includes(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 将自动缓解大多数版本偏差的情况,并在检测到时自动重新加载应用程序以检索新资源。For example,如果deploymentId 不匹配,页面之间的过渡将执行硬导航,而不是使用预取的值。
当应用程序重新加载时,如果没有设计为在页面导航之间持久化,可能会丢失应用程序状态。例如,使用 URL 状态或本地存储可以在页面刷新后持久化状态。然而,像useState这样的组件状 态将在此类导航中丢失。
Vercel 为 Next.js 应用程序提供额外的版本偏差保护,以确保即使在新版本部署后,旧客户端仍然可以访问以前版本的资源和功能。
您可以在next.config.js文件中手动配置deploymentId属性,以确保每个请求使用?dpl询字符串或x-deployment-id头。
Streaming 和 Suspense
Next.js App Router 在自托管时支持流式响应。如果您使用 Nginx 或类似的代理,您需要配置它以禁用 buffering 来启用流式传输。
例如,您可以通过将X-Accel-Buffering设置为no来禁用 Nginx 中的 buffering:
module.exports = {
async headers() {
return [
{
source: "/:path*{/}?",
headers: [
{
key: "X-Accel-Buffering",
value: "no",
},
],
},
];
},
};
部分预渲染
部分预渲染(实验性)默认与 Next.js 配合使用,并且不是 CDN 功能。这包括作为 Node.js 服务器(通过 next start)部署以及与 Docker 容器一起使用时。
与 CDNs 一起使用
在 Next.js 应用程序的前端使用 CDN 时,当访问动态 API 时,页面将包含Cache-Control: private响应头。这确保生成的 HTML 页面被标记为不可缓存。如果页面完全预渲染为静态页面,它将包含Cache-Control: public,以允许页面在 CDN 上缓存。
如果您不需要混合使用静态和动态组件,您可以将整个路由设为静态, 并将输出的 HTML 缓存到 CDN 上。如果未使用动态 API,在运行next build时,自动静态优化则是默认行为。