部署
恭喜,现在可以交付生产了。
¥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.
-
你机器上的 安装 Docker
¥Install Docker on your machine
-
¥Clone our example (or the multi-environment example)
-
构建你的容器:
docker build -t nextjs-docker .
¥Build your container:
docker build -t nextjs-docker .
-
运行你的容器:
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:
服务器组件 支持静态导出。
¥Server Components are supported with static exports.
特性
¥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 作为 服务器组件。例如,检查 headers 和 redirecting。你还可以对 redirect 或 rewrite 到 next.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:
你可以使用
register
功能.conf 在服务器启动时运行代码。¥You can run code on server startup using the
register
function.我们不建议使用 runtimeConfig 选项,因为这不适用于独立输出模式。相反,我们推荐 逐步采用 应用路由。
¥We do not recommend using the runtimeConfig option, as this does not work with the standalone output mode. Instead, we recommend incrementally adopting the App Router.
缓存和 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, immutable
的Cache-Control
标头设置为真正不可变的资源。它不能被覆盖。这些不可变文件的文件名中包含 SHA 哈希值,因此可以无限期安全地缓存它们。例如,静态图片导入。你可以对图片进行 配置 TTL。¥Next.js sets the
Cache-Control
header ofpublic, 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-revalidate
的Cache-Control
标头。此重新验证时间在getStaticProps
功能 中以秒为单位定义。如果设置revalidate: false
,则默认缓存期限为一年。¥Incremental Static Regeneration (ISR) sets the
Cache-Control
header ofs-maxage: <revalidate in getStaticProps>, stale-while-revalidate
. This revalidation time is defined in yourgetStaticProps
function in seconds. If you setrevalidate: 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 ofprivate, 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.
¥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. CallingrevalidatePath
will call therevalidateTag
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
.
停止服务器时,通过发送 SIGINT
或 SIGTERM
信号并等待来确保正常关闭。这允许 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))
}