Skip to content

NextJS中文文档 - Self Hosting

部署你的 Next.js 应用程序时,你可能希望根据你的基础设施配置不同功能的处理方式。

🎥 观看: 了解更多关于自托管 Next.js 的信息 → YouTube(45分钟)

图像优化

通过 next/image 进行的图像优化在使用 next start 部署时可以零配置自托管。如果你更喜欢使用单独的服务来优化图像,你可以配置图像加载器

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

须知:/nextjs-cn/

  • 在基于 glibc 的 Linux 系统上,图像优化可能需要额外配置以防止过度内存使用。
  • 了解更多关于优化图像的缓存行为以及如何配置 TTL。
  • 如果你愿意,你也可以禁用图像优化,同时保留使用 next/image 的其他好处。例如,如果你自己单独优化图像。

中间件/nextjs-cn/

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

  • 中间件使用 Edge 运行时,这是所有可用 Node.js API 的子集,有助于确保低延迟,因为它可能在应用程序中的每个路由或资源之前运行。如果你不想这样,你可以使用完整的 Node.js 运行时来运行中间件。

如果你想添加需要所有 Node.js),你可能可以将此逻辑移至布局中作为服务器组件。例如,检查头信息重定向。你还可以使用头信息、cookies 或查询参数通过 next.config.js 进行重定向重写。如果这些方法都不能满足需求,你还可以使用自定义服务器

环境变量

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

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

这允许你使用单一的 Docker 镜像,可以在具有不同值的多个环境中提升。

须知:

  • 你可以使用 register 函数 在服务器启动时运行代码。
  • 我们不建议使用 runtimeConfig 选项,因为它不适用于独立输出模式。相反,我们建议逐步采用 App Router。

缓存和 ISR

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

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

如果你想将缓存的页面和数据持久化到持久存储,/nextjs-cn/程序容器或实例之间共享缓存,则可以配置 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 Router 和 Pages Router。这也/nextjs-cn/extjs-cn/app/guides/draft-mode)。/nextjs-cn/ /nextjs-cn/

静态资源/nextjs-cn/

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

了解更多关于 assetPrefix

配置缓存/nextjs-cn/

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

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

jsx
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // 禁用默认的内存缓存
}

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

jsx
const cache = new Map()

module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }

  async get(key) {
    // 这可以存储在任何地方,如持久存储
    return cache.get(key)
  }

  async set(key, data, ctx) {
    // 这可以存储在任何地方,如持久存储
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }

  async revalidateTag(tags) {
    // tags 是一个字符串或字符串数组
    tags = [tags].flat()
    // 迭代缓存中的所有条目
    for (let [key, value] of cache) {
      // 如果值的标签包含指定的标签,删除此条目
      if (value.tags.some((tag) => tags.includes(tag))) {
        cache.delete(key)
      }
    }
  }

  // 如果你想为单个请求有临时内存缓存,并在
  // 下一个请求前重置,你可以利用此方法
  resetRequestCache() {}
}

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

须知:

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

构建缓存

Next.js 在 next build 期间生成一个 ID 来标识正在提供的应用程序版本。相同的构建应该被使用并引导多个容器。

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

jsx
module.exports = {
  generateBuildId: async () => {
    // 这可以是任何东西,使用最新的 git hash
    return process.env.GIT_HASH
  },
}

版本倾斜

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

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

🎉有任何问题,欢迎联系我

WeChat QR Code
WeChat
QQ QR Code
QQ

赣ICP备2023003243号