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
无哈希的文件
其他来自应用 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 调用的响应数据,其中可能包含敏感信息。请确保这些文件不被公开访问。
重新验证表
创建一个 DynamoDB 表,配置如下:
- 分区键:
tag
(字符串类型) - 排序键:
path
(字符串类型) - 创建一个名为
revalidate
的索引,配置如下:- 分区键:
path
(字符串类型) - 排序键:
revalidatedAt
(数字类型)
- 分区键:
图片优化函数
使用 .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 模式会生成包含处理请求的 NextServer 类的 .next
文件夹,以及运行 NextServer
所需的 所有依赖项 的 node_modules
文件夹。结构如下:
.next/ -> NextServer
node_modules/ -> 依赖项
server 函数适配器封装了 NextServer
并导出一个支持 Lambda 请求和响应的处理器函数。server-function
打包后的结构如下:
.next/ -> NextServer
+ .open-next/
node_modules/ -> 依赖项
+ index.mjs -> server 函数适配器
Monorepo 项目
在 monorepo 项目中,构建输出的结构会稍有不同。例如,如果应用位于 packages/web
目录下,构建输出将呈现如下结构:
packages/
web/
.next/ -> NextServer 服务器
node_modules/ -> 来自根目录 node_modules 的依赖项(可选)
node_modules/ -> 来自包目录 node_modules 的依赖项
这种情况下,服务器函数适配器需要创建在 packages/web
目录下,与 .next/
同级。这是为了确保适配器能够同时从两个 node_modules
文件夹导入依赖项。我们不建议将 Lambda 配置与项目结构耦合,因此不会直接将 Lambda 处理器设置为 packages/web/index.mjs
,而是在 server-function
打包根目录添加一个重新导出适配器的包装器 index.mjs
。最终的结构如下所示:
packages/
web/
.next/ -> NextServer 服务器
+ .open-next/
node_modules/ -> 来自根目录 node_modules 的依赖项(可选)
+ index.mjs -> 服务器函数适配器
node_modules/ -> 来自包目录 node_modules 的依赖项
+ index.mjs -> 适配器包装器
这样可以确保 Lambda 处理器始终指向根目录的 index.mjs
。
CloudFront 分发配置
创建一个 CloudFront 分发,并将请求分发到对应的处理程序(行为)。配置了以下行为:
行为 | 请求类型 | CloudFront 函数 | 源站 |
---|---|---|---|
/_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 负载版本 2.0)和边缘请求事件(CloudFront Origin Request 负载)。根据 Lambda 事件对象的格式,函数会相应地处理请求。
配置 CloudFront 分配的方案:
行为 | 请求类型 | CloudFront 函数 | 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 分钟调用一次预热函数。
了解更多关于预热工作原理。
DynamoDB 提供者函数
此函数用于填充重新验证表。它是 CDK 中的一个自定义资源处理程序,详见此处 (opens in a new tab)。确保函数配置如下:
- 设置
CACHE_DYNAMO_TABLE
环境变量,其值为存储重新验证表的 DynamoDB 表名称 - 授予
dynamodb:PutItem
权限,允许函数写入 DynamoDB 表