AWS 上的推荐基础设施
OpenNext 不会创建底层基础设施。你可以使用首选工具为应用创建基础设施——SST、AWS CDK、Terraform、Serverless Framework 等。
这是推荐的设置。

以下是每个 AWS 资源的推荐配置。
资源文件
创建一个 S3 存储桶,并将 .open-next/assets 文件夹中的内容上传到存储桶的根目录。例如,文件 .open-next/assets/favicon.ico 应上传到存储桶根目录的 /favicon.ico。如果你需要将文件上传到存储桶内的子文件夹,参考本节。
.open-next/assets 文件夹中有两种类型的文件:
哈希文件
这些是文件名中包含哈希组件的文件。哈希文件位于 .open-next/assets/_next 文件夹中,例如 .open-next/assets/_next/static/css/0275f6d90e7ad339.css。当文件内容被修改时,文件名中的哈希值保证会更改。因此,哈希文件应在 CDN 级别和浏览器级别都进行缓存。将哈希文件上传到 S3 时,推荐的缓存控制设置是
public,max-age=31536000,immutable非哈希文件
.open-next/assets 文件夹中的其他文件是从应用的 public/ 文件夹复制的,例如 .open-next/assets/favicon.ico。当内容被修改时,非哈希文件的文件名可能保持不变。非哈希文件应在 CDN 级别缓存,但不在浏览器级别缓存。当非哈希文件的内容被修改时,部署时应使 CDN 缓存失效。将非哈希文件上传到 S3 时,推荐的缓存控制设置是
public,max-age=0,s-maxage=31536000,must-revalidate缓存文件
创建一个 S3 存储桶,并将 .open-next/cache 文件夹中的内容上传到存储桶的根目录。如果你需要将文件上传到存储桶内的子文件夹,参考本节。
.open-next/cache 文件夹中有两种类型的缓存:
- 路由缓存:此缓存包括构建期间预渲染的
html和json文件。它们用于种子重新验证缓存。 - Fetch 缓存:此缓存包括 fetch 调用响应,其中可能包含敏感信息。确保这些文件不可公开访问。
重新验证表
创建一个具有以下配置的 DynamoDB 表:
- 分区键:
tag(String) - 排序键:
path(String) - 一个名为
revalidate的索引,具有以下配置:- 分区键:
path(String) - 排序键:
revalidatedAt(Number)
- 分区键:
图像优化函数
使用 .open-next/image-optimization-function 文件夹中的代码创建一个 Lambda 函数,处理程序为 index.mjs。此外,确保函数配置如下:
- 将架构设置为
arm64。 - 设置
BUCKET_NAME环境变量,值为存储原始图像的 S3 存储桶的名称。 - 如果资源文件上传到 S3 存储桶中的子文件夹,则设置
BUCKET_KEY_PREFIX环境变量。值为文件夹的路径。这是可选的。 - 授予
s3:GetObject权限。
当使用 Next.js <Image> 组件时,此函数处理图像优化请求。函数捆绑的 sharp (opens in a new tab) 库用于转换图像。该库针对 arm64 架构编译,旨在运行在 AWS Lambda Arm/Graviton2 架构上。了解 AWS Graviton2 处理器提供的更佳性价比。 (opens in a new tab)
请注意,图像优化函数响应 Cache-Control 标头,因此图像将在 CDN 级别和浏览器级别都进行缓存。
Server Lambda 函数
使用 .open-next/server-function 文件夹中的代码创建一个 Lambda 函数,处理程序为 index.mjs。此外,确保函数配置如下:
- 设置
CACHE_BUCKET_NAME环境变量,值为存储缓存文件的 S3 存储桶的名称。 - 如果缓存文件上传到 S3 存储桶中的子文件夹,则设置
CACHE_BUCKET_KEY_PREFIX环境变量。值为文件夹的路径。这是可选的。 - 设置
CACHE_BUCKET_REGION环境变量,值为 S3 存储桶的区域。 - 设置
REVALIDATION_QUEUE_URL环境变量,值为重新验证队列的 URL。 - 设置
REVALIDATION_QUEUE_REGION环境变量,值为重新验证队列的区域。 - 设置
CACHE_DYNAMO_TABLE环境变量,值为重新验证表的名称。 - 授予
s3:GetObject、s3:PutObject和s3:ListObjects权限。 - 授予
sqs:SendMessage权限。
此函数处理来自 Next.js 应用的所有其他类型的请求,包括服务器端渲染 (SSR) 请求和 API 请求。OpenNext 以 standalone 模式构建 Next.js 应用。standalone 模式生成一个 .next 文件夹,其中包含处理请求的 NextServer 类,以及一个 node_modules 文件夹,其中包含运行 NextServer 所需的所有依赖项。结构如下:
.next/ -> NextServer
node_modules/ -> 依赖项服务器函数适配器包装了 NextServer 并导出一个支持 Lambda 请求和响应的处理函数。server-function bundle 如下所示:
.next/ -> NextServer
+ .open-next/
node_modules/ -> 依赖项
+ index.mjs -> 服务器函数适配器Monorepo
在 monorepo 的情况下,构建输出看起来略有不同。例如,如果应用位于 packages/web,则构建输出如下所示:
packages/
web/
.next/ -> NextServer
node_modules/ -> 来自根 node_modules 的依赖项 (可选)
node_modules/ -> 来自 package node_modules 的依赖项在这种情况下,服务器函数适配器需要在 .next/ 旁边的 packages/web 内部创建。这是为了确保适配器可以从两个 node_modules 文件夹导入依赖项。将 Lambda 配置与项目结构耦合并不是一个好的做法,因此我们不会将 Lambda 处理程序设置为 packages/web/index.mjs,而是在 server-function bundle 根目录添加一个包装器 index.mjs 来重新导出适配器。结果结构如下所示:
packages/
web/
.next/ -> NextServer
+ .open-next/
node_modules/ -> 来自根 node_modules 的依赖项 (可选)
+ index.mjs -> 服务器函数适配器
node_modules/ -> 来自 package node_modules 的依赖项
+ index.mjs -> 适配器包装器这确保 Lambda 处理程序保持在 index.mjs。
CloudFront 分发
创建一个 CloudFront 分发,并将请求分发到相应的处理程序(行为)。配置了以下行为:
| 行为 | 请求 | CloudFront Function | 源 |
|---|---|---|---|
/_next/static/* | 哈希静态文件 | - | S3 存储桶 |
/favicon.ico/my-images/*查看原因 | 公共资源 | - | S3 存储桶 |
/_next/image | 图像优化 | - | 图像优化函数 |
/_next/data/* | 数据请求 | 设置 x-forwarded-host查看原因 | 服务器函数 |
/api/* | API | 设置 x-forwarded-host查看原因 | 服务器函数 |
/* | 捕获所有 | 设置 x-forwarded-host查看原因。另外 参见此处 | 服务器函数 |
在边缘运行
通过将其配置为 Origin Request 上的 Lambda@Edge,服务器函数也可以在边缘位置运行。服务器函数可以接受区域请求事件(API payload 版本 2.0)和边缘请求事件(CloudFront Origin Request payload)。根据 Lambda 事件对象的形状,函数将相应地处理请求。
要配置 CloudFront 分发:
| 行为 | 请求 | CloudFront Function | Lambda@Edge | 源 |
|---|---|---|---|---|
/_next/static/* | 哈希静态文件 | - | - | S3 存储桶 |
/favicon.ico/my-images/*查看原因 | 公共资源 | - | - | S3 存储桶 |
/_next/image | 图像优化 | - | - | 图像优化函数 |
/_next/data/* | 数据请求 | 设置 x-forwarded-host查看原因 | 服务器函数 | - |
/api/* | API | 设置 x-forwarded-host查看原因 | 服务器函数 | - |
/* | 捕获所有 | 设置 x-forwarded-host查看原因 | 服务器函数 | - |
重新验证函数
使用 .open-next/revalidation-function 文件夹中的代码创建一个 Lambda 函数,处理程序为 index.mjs。
此外,创建一个 SQS FIFO 队列,并将其设置为该函数的事件源。
此函数轮询队列以获取重新验证消息。收到消息后,函数向指定路由发送 HEAD 请求以进行重新验证。
预热函数
使用 .open-next/warmer-function 文件夹中的代码创建一个 Lambda 函数,处理程序为 index.mjs。确保函数配置如下:
- 设置
FUNCTION_NAME环境变量,值为服务器 Lambda 函数的名称。 - 设置
CONCURRENCY环境变量,值为要预热的服务器函数数量。 - 授予
lambda:InvokeFunction权限以允许预热器调用服务器函数。
此外,创建一个 EventBridge 计划规则,每 5 分钟调用一次预热函数。
阅读更多关于 预热工作原理 的信息。
Dynamo Provider 函数
此函数用于填充重新验证表。它是来自 cdk 的自定义资源处理程序,参见 此处 (opens in a new tab)。确保函数配置如下:
- 设置
CACHE_DYNAMO_TABLE环境变量,值为存储重新验证表的 DynamoDB 表的名称。 - 授予
dynamodb:PutItem权限以允许函数写入 DynamoDB 表。