来自 AWS CloudFront 的外部 Next.js 图像的缓存控制策略对于 Google Lighthouse 来说效率不高

Cri*_*jas 3 cache-control amazon-web-services lighthouse next.js nextjs-image

我正在尝试通过修复 Google Lighthouse 报告的所有问题来优化我的 Next.js 应用程序。

目前它在图像方面最重要的缺陷之一:

通过高效的缓存策略提供静态资源

根据文档static,Next.js 自动对文件夹中的媒体执行此操作

Next.js 自动将缓存标头添加到 /_next/static 提供的不可变资产中,包括 JavaScript、CSS、静态图像和其他媒体。

由于所有这些有问题的图像都来自 API,该 API 由 AWS CloudFront 提供服务,因此我找不到解决问题的方法。

我想Cache-Control在 CloudFront 中添加建议的策略可能会有所帮助,但我不知道

1.) 如果这是正确的解决方案 2.) 如何在 AWS 控制台中执行此操作

htm*_*tmn 6

Next.js 自动将缓存标头添加到 /_next/static 提供的不可变资产中,包括 JavaScript、CSS、静态图像和其他媒体。

next export当您使用静态站点并将其部署到 S3 和 CloudFront 时,情况并非如此,请参阅不支持的功能(尽管他们没有明确说明)。您可以做的是使用S3 对象元数据手动设置这些Cache-Control标头。这是 next.js 应用程序的首选方式,因为您可以单独指定每个对象的标头。

通常(请参阅缓存最佳实践和 max-age 陷阱)您应该max-age=31536000,public,immutable向整个_next/static文件夹添加指令,因为这些指令会将哈希值附加到文件名中,因此每次新更改时缓存都会失效。

除此之外,它是由您管理的,并且取决于您正在构建的应用程序类型,但通常的做法是将 HTML 文档设置为public,max-age=0,must-revalidate(甚至no-cache,no-store)。由于您使用的是 CloudFront,只要您设置了正确的失效设置,就可以将它们保留在边缘缓存中。

您还可能有非静态导入的图像src="<path string>",这些图像也不会导出到_next/static文件夹中,因此如果您想将long max-age&添加immutable content到这些图像中,您必须自己管理版本控制/散列,以便在图像更改时正确失效。

使用 AWS 控制台

在 Amazon S3 控制台中签出编辑对象元数据,以将Cache-Control标头添加到_next/static对象元数据:

  1. 打开 Amazon S3 控制台和您的存储桶。
  2. 选中目录左侧的复选框_next/
  3. 在操作菜单上,选择编辑操作,然后选择编辑元数据。
  4. 选择添加元数据。
  5. 对于元数据类型,选择系统定义。
  6. 选择Cache-Control键并添加max-age=31536000,public,immutable为值。
  7. 完成后,点击“保存更改”,Amazon S3 应递归编辑所有_next/static文件元数据,您可以通过打开特定文件并向下滚动到元数据部分来验证它。

含CDK

如果您使用 AWS CDK,则可以使用多个构造为不同目录BucketDeployment指定不同标头(请参阅示例):Cache-Controlout

// _next/static - long max-age & immutable content
new s3deploy.BucketDeployment(this, 'BucketDeployment', {
  ...
  sources: [s3deploy.Source.asset('./out', { exclude: [ '/**/*', '!/_next/static/**/*'] })],
  cacheControl: [s3deploy.CacheControl.fromString('max-age=31536000,public,immutable')],
  ...
});

// revalidate everything else
new s3deploy.BucketDeployment(this, 'BucketDeployment', {
  ...
  sources: [s3deploy.Source.asset('./out', { exclude: ['/_next/static/**/*'] })],
  cacheControl: [s3deploy.CacheControl.fromString('max-age=0,no-cache,no-store,must-revalidate')],
  ...
});
Run Code Online (Sandbox Code Playgroud)

无需 Vercel 即可改进

我还建议(如果使用一些额外的 AWS 资源并且 terraform 不是问题)看看这个terraform 模块,或者至少看看它们的图像优化器,它可以作为 Next.js 图像组件的独立图像优化加载器放入,这样您就可以获得所有next/image组件的好处(许多其他解决方法也存在这个问题)。