跳到主要内容

部署

恭喜,现在可以交付生产了。

¥Congratulations, it's time to ship to production.

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

¥You can deploy managed Next.js with Vercel, or self-host on a Node.js server, Docker image, or even static HTML files. When deploying using next start, all Next.js features are supported.

生产构建

¥Production Builds

运行 next build 会生成用于生产的应用的优化版本。HTML、CSS 和 JavaScript 文件是根据你的页面创建的。使用 Next.js 编译器 编译 JavaScript 并缩小浏览器打包包,以帮助实现最佳性能并支持 所有现代浏览器

¥Running next build generates an optimized version of your application for production. HTML, CSS, and JavaScript files are created based on your pages. JavaScript is compiled and browser bundles are minified using the Next.js Compiler to help achieve the best performance and support all modern browsers.

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

¥Next.js produces a standard deployment output used by managed and self-hosted Next.js. This ensures all features are supported across both methods of deployment. In the next major version, we will be transforming this output into our Build Output API specification.

使用 Vercel 管理 Next.js

¥Managed Next.js with Vercel

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

¥Vercel, the creators and maintainers of Next.js, provide managed infrastructure and a developer experience platform for your Next.js applications.

部署到 Vercel 是零配置,并为全局可扩展性、可用性和性能提供了额外的增强功能。但是,自托管时仍然支持所有 Next.js 功能。

¥Deploying to Vercel is zero-configuration and provides additional enhancements for scalability, availability, and performance globally. However, all Next.js features are still supported when self-hosted.

了解有关 Vercel 上的 Next.js免费部署模板 的更多信息来尝试一下。

¥Learn more about Next.js on Vercel or deploy a template for free to try it out.

自托管

¥Self-Hosting

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

¥You can self-host Next.js in three different ways:

🎥 监视:了解有关自托管 Next.js → YouTube(45 分钟) 的更多信息。

¥🎥 Watch: Learn more about self-hosting Next.js → YouTube (45 minutes).

我们有社区维护的部署示例,其中包含以下提供程序:

¥We have community maintained deployment examples with the following providers:

Node.js 服务器

¥Node.js Server

Next.js 可以部署到任何支持 Node.js 的托管提供商。确保你的 package.json 具有 "build""start" 脚本:

¥Next.js can be deployed to any hosting provider that supports Node.js. Ensure your package.json has the "build" and "start" scripts:

{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}

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

¥Then, run npm run build to build your application. Finally, run npm run start to start the Node.js server. This server supports all Next.js features.

Docker 镜像

¥Docker Image

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

¥Next.js can be deployed to any hosting provider that supports Docker containers. You can use this approach when deploying to container orchestrators such as Kubernetes or when running inside a container in any cloud provider.

  1. 你机器上的 安装 Docker

    ¥Install Docker on your machine

  2. 克隆我们的示例(或 多环境示例

    ¥Clone our example (or the multi-environment example)

  3. 构建你的容器:docker build -t nextjs-docker .

    ¥Build your container: docker build -t nextjs-docker .

  4. 运行你的容器:docker run -p 3000:3000 nextjs-docker

    ¥Run your container: docker run -p 3000:3000 nextjs-docker

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

¥Next.js through Docker supports all Next.js features.

静态 HTML 导出

¥Static HTML Export

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

¥Next.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server.

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

¥Since Next.js supports this static export, it can be deployed and hosted on any web server that can serve HTML/CSS/JS static assets. This includes tools like AWS S3, Nginx, or Apache.

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

¥Running as a static export does not support Next.js features that require a server. Learn more.

很高兴知道:

¥Good to know:

特性

¥Features

图片优化

¥Image Optimization

使用 next start 部署时,图片优化next/image 以零配置自托管。如果你希望使用单独的服务来优化图片,你可以 配置图片加载器

¥Image Optimization through next/image works self-hosted with zero configuration when deploying using next start. If you would prefer to have a separate service to optimize images, you can configure an image loader.

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

¥Image Optimization can be used with a static export by defining a custom image loader in next.config.js. Note that images are optimized at runtime, not during the build.

很高兴知道:

¥Good to know:

  • 在基于 glibc 的 Linux 系统上,图片优化可能需要 附加配置 来防止过度使用内存。

    ¥On glibc-based Linux systems, Image Optimization may require additional configuration to prevent excessive memory usage.

  • 了解有关 优化图片的缓存行为 以及如何配置 TTL 的更多信息。

    ¥Learn more about the caching behavior of optimized images and how to configure the TTL.

  • 如果你愿意,你也可以选择 禁用图片优化,同时仍然保留使用 next/image 的其他好处。例如,如果你自己单独优化图片。

    ¥You can also disable Image Optimization and still retain other benefits of using next/image if you prefer. For example, if you are optimizing images yourself separately.

中间件

¥Middleware

使用 next start 部署时,中间件 以零配置自托管工作。由于它需要访问传入请求,因此使用 静态导出 时不支持它。

¥Middleware works self-hosted with zero configuration when deploying using next start. Since it requires access to the incoming request, it is not supported when using a static export.

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

¥Middleware uses a runtime that is a subset of all available Node.js APIs to help ensure low latency, since it may run in front of every route or asset in your application. This runtime does not require running “at the edge” and works in a single-region server. Additional configuration and infrastructure are required to run Middleware in multiple regions.

如果你希望添加需要所有 Node.js API 的逻辑(或使用外部包),你也许可以将此逻辑移至 layout 作为 服务器组件。例如,检查 headersredirecting。你还可以对 redirectrewritenext.config.js 使用标头、cookie 或查询参数。如果这不起作用,你还可以使用 定制服务器

¥If you are looking to add logic (or use an external package) that requires all Node.js APIs, you might be able to move this logic to a layout as a Server Component. For example, checking headers and redirecting. You can also use headers, cookies, or query parameters to redirect or rewrite through next.config.js. If that does not work, you can also use a custom server.

环境变量

¥Environment Variables

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

¥Next.js can support both build time and runtime environment variables.

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

¥By default, environment variables are only available on the server. To expose an environment variable to the browser, it must be prefixed with NEXT_PUBLIC_. However, these public environment variables will be inlined into the JavaScript bundle during next build.

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

¥You safely read environment variables on the server during dynamic rendering.

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
// ...
}
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 映像,该映像可以通过具有不同值的多个环境进行提升。

¥This allows you to use a singular Docker image that can be promoted through multiple environments with different values.

很高兴知道:

¥Good to know:

缓存和 ISR

¥Caching and ISR

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

¥Next.js can cache responses, generated static pages, build outputs, and other static assets like images, fonts, and scripts.

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

¥Caching and revalidating pages (with Incremental Static Regeneration) use the same shared cache. By default, this cache is stored to the filesystem (on disk) on your Next.js server. This works automatically when self-hosting using both the Pages and App Router.

如果你想要将缓存的页面和数据持久保存到持久存储,或者在 Next.js 应用的多个容器或实例之间共享缓存,你可以配置 Next.js 缓存位置。

¥You can configure the Next.js cache location if you want to persist cached pages and data to durable storage, or share the cache across multiple containers or instances of your Next.js application.

自动缓存

¥Automatic Caching

  • Next.js 将 public, max-age=31536000, immutableCache-Control 标头设置为真正不可变的资源。它不能被覆盖。这些不可变文件的文件名中包含 SHA 哈希值,因此可以无限期安全地缓存它们。例如,静态图片导入。你可以对图片进行 配置 TTL

    ¥Next.js sets the Cache-Control header of public, max-age=31536000, immutable to truly immutable assets. It cannot be overridden. These immutable files contain a SHA-hash in the file name, so they can be safely cached indefinitely. For example, Static Image Imports. You can configure the TTL for images.

  • 增量静态再生 (ISR) 设置 s-maxage: <revalidate in getStaticProps>, stale-while-revalidateCache-Control 标头。此重新验证时间在 getStaticProps 功能 中以秒为单位定义。如果设置 revalidate: false,则默认缓存期限为一年。

    ¥Incremental Static Regeneration (ISR) sets the Cache-Control header of s-maxage: <revalidate in getStaticProps>, stale-while-revalidate. This revalidation time is defined in your getStaticProps function in seconds. If you set revalidate: false, it will default to a one-year cache duration.

  • 动态渲染的页面将 Cache-Control 标头设置为 private, no-cache, no-store, max-age=0, must-revalidate,以防止缓存用户特定的数据。这适用于 App Router 和 Pages Router。这也包括 草稿模式

    ¥Dynamically rendered pages set a Cache-Control header of private, no-cache, no-store, max-age=0, must-revalidate to prevent user-specific data from being cached. This applies to both the App Router and Pages Router. This also includes Draft Mode.

静态资源

¥Static Assets

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

¥If you want to host static assets on a different domain or CDN, you can use the assetPrefix configuration in next.config.js. Next.js will use this asset prefix when retrieving JavaScript or CSS files. Separating your assets to a different domain does come with the downside of extra time spent on DNS and TLS resolution.

了解有关 assetPrefix 的更多信息

¥Learn more about assetPrefix.

配置缓存

¥Configuring Caching

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

¥By default, generated cache assets will be stored in memory (defaults to 50mb) and on disk. If you are hosting Next.js using a container orchestration platform like Kubernetes, each pod will have a copy of the cache. To prevent stale data from being shown since the cache is not shared between pods by default, you can configure the Next.js cache to provide a cache handler and disable in-memory caching.

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

¥To configure the ISR/Data Cache location when self-hosting, you can configure a custom handler in your next.config.js file:

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

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

¥Then, create cache-handler.js in the root of your project, for example:

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
public resetRequestCache() {}
}

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

¥Using a custom cache handler will allow you to ensure consistency across all pods hosting your Next.js application. For instance, you can save the cached values anywhere, like Redis or AWS S3.

很高兴知道:

¥Good to know:

  • revalidatePath 是缓存标签之上的便利层。调用 revalidatePath 将调用 revalidateTag 函数,并为所提供的页面提供特殊的默认标记。

    ¥revalidatePath is a convenience layer on top of cache tags. Calling revalidatePath will call the revalidateTag function with a special default tag for the provided page.

构建缓存

¥Build Cache

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

¥Next.js generates an ID during next build to identify which version of your application is being served. The same build should be used and boot up multiple containers.

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

¥If you are rebuilding for each stage of your environment, you will need to generate a consistent build ID to use between containers. Use the generateBuildId command in next.config.js:

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

版本偏差

¥Version Skew

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

¥Next.js will automatically mitigate most instances of version skew and automatically reload the application to retrieve new assets when detected. For example, if there is a mismatch in the deploymentId, transitions between pages will perform a hard navigation versus using a prefetched value.

重新加载应用时,如果应用状态未设计为在页面导航之间保留,则可能会丢失应用状态。例如,使用 URL 状态或本地存储将在页面刷新后保留状态。但是,像 useState 这样的组件状态会在此类导航中丢失。

¥When the application is reloaded, there may be a loss of application state if it's not designed to persist between page navigations. For example, using URL state or local storage would persist state after a page refresh. However, component state like useState would be lost in such navigations.

Vercel 为 Next.js 应用提供了额外的 倾斜保护,以确保即使在部署新版本之后,旧版本的资源和功能仍然可供旧客户端使用。

¥Vercel provides additional skew protection for Next.js applications to ensure assets and functions from the previous version are still available to older clients, even after the new version is deployed.

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

¥You can manually configure the deploymentId property in your next.config.js file to ensure each request uses either ?dpl query string or x-deployment-id header.

流式和悬念

¥Streaming and Suspense

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

¥The Next.js App Router supports streaming responses when self-hosting. If you are using Nginx or a similar proxy, you will need to configure it to disable buffering to enable streaming.

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

¥For example, you can disable buffering in Nginx by setting X-Accel-Buffering to no:

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

部分预渲染

¥Partial Prerendering

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

¥Partial Prerendering (experimental) works by default with Next.js and is not a CDN feature. This includes deployment as a Node.js server (through next start) and when used with a Docker container.

与 CDN 一起使用

¥Usage with CDNs

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

¥When using a CDN in front on your Next.js application, the page will include Cache-Control: private response header when dynamic APIs are accessed. This ensures that the resulting HTML page is marked as non-cachable. If the page is fully prerendered to static, it will include Cache-Control: public to allow the page to be cached on the CDN.

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

¥If you don't need a mix of both static and dynamic components, you can make your entire route static and cache the output HTML on a CDN. This Automatic Static Optimization is the default behavior when running next build if dynamic APIs are not used.

after

使用 next start 自托管时,完全支持 after

¥after is fully supported when self-hosting with next start.

停止服务器时,通过发送 SIGINTSIGTERM 信号并等待来确保正常关闭。这允许 Next.js 服务器等到 after 内部使用的待处理回调函数或promise完成后。

¥When stopping the server, ensure a graceful shutdown by sending SIGINT or SIGTERM signals and waiting. This allows the Next.js server to wait until after pending callback functions or promises used inside after have finished.

如果你想在自定义基础架构上使用 after,请查看你的提供商文档以查看对 after 的支持。

¥If you want to use after on custom infrastructure, check your provider documentation to view support for after.

Details

Reference: supporting after for serverless platforms 在无服务器上下文中使用 after 需要在发送响应后等待异步任务完成。在 Next.js 和 Vercel 中,这是使用名为 waitUntil(promise) 的原语实现的,它延长了无服务器调用的生命周期,直到传递给 waitUntil 的所有promise都已解决。

¥

Reference: supporting after for serverless platforms Using after in a serverless context requires waiting for asynchronous tasks to finish after the response has been sent. In Next.js and Vercel, this is achieved using a primitive called waitUntil(promise), which extends the lifetime of a serverless invocation until all promises passed to waitUntil have settled.

如果你希望用户能够运行 after,则必须提供以类似方式运行的 waitUntil 实现。

¥If you want your users to be able to run after, you will have to provide your implementation of waitUntil that behaves in an analogous way.

调用 after 时,Next.js 将像这样访问 waitUntil

¥When after is called, Next.js will access waitUntil like this:

const RequestContext = globalThis[Symbol.for('@next/request-context')]
const contextValue = RequestContext?.get()
const waitUntil = contextValue?.waitUntil

这意味着 globalThis[Symbol.for('@next/request-context')] 应该包含这样的对象:

¥Which means that globalThis[Symbol.for('@next/request-context')] is expected to contain an object like this:

type NextRequestContext = {
get(): NextRequestContextValue | undefined
}

type NextRequestContextValue = {
waitUntil?: (promise: Promise<any>) => void
}

以下是实现的示例。

¥Here is an example of the implementation.

import { AsyncLocalStorage } from 'node:async_hooks'

const RequestContextStorage = new AsyncLocalStorage<NextRequestContextValue>()

// Define and inject the accessor that next.js will use
const RequestContext: NextRequestContext = {
get() {
return RequestContextStorage.getStore()
},
}
globalThis[Symbol.for('@next/request-context')] = RequestContext

const handler = (req, res) => {
const contextValue = { waitUntil: YOUR_WAITUNTIL }
// Provide the value
return RequestContextStorage.run(contextValue, () => nextJsHandler(req, res))
}