You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS ECS/Fargate上缓存Next.js动态路由SSR页面

在AWS ECS/Fargate上缓存Next.js SSR页面的实现方案

问题背景

我正在AWS上使用ECS/Fargate部署Next.js应用(因需自定义日志与监控,无法使用Amplify)。该应用采用api-routes及带getServerSideProps的动态路由实现服务端渲染(SSR),SSR页面URL示例为:domain.com/foopage/[id]?powerlevel=10000,代码如下:

// pages/foopage/[id].tsx

import React from "react";
import type { GetServerSideProps } from "next";
import Head from "next/head";

export default function FooPage({ id }: Record<string, string>) {
  return (
    <div>
      <Head>
        <title>Title</title>
      </Head>
      <main>
        <h1>
          Say Hi to <a href="https://sample-url.com/id">{id}</a>!
        </h1>
      </main>
    </div>
  );
}

export const getServerSideProps: GetServerSideProps = async (context) => {
  context.res.setHeader(
    "Cache-Control",
    "public, s-maxage=10, stale-while-revalidate=59"
  );
  const { id } = context.query;
  const response = await fetch(
    `${process.env.CMS_URL}/api/configurations?id=${id}`
  );
  const jsonResponse = await response.json();

  return {
    props: { id },
  };
};

希望缓存这些页面,避免服务器每次都重新生成。已知在Vercel上无需配置即可实现边缘缓存,但因业务要求必须使用AWS,请问在AWS中具体该如何实现?是否可通过Lambda@Edge实现?若可以,对应的Lambda函数示例是什么?


解决方案:CloudFront + Lambda@Edge

可以通过CloudFront(AWS边缘CDN)配合Lambda@Edge实现类似Vercel的边缘缓存效果,具体实现步骤如下:

1. 基础架构配置

  • 将CloudFront分发的源(Origin)指向你的ECS/Fargate应用对应的ALB(应用负载均衡器)域名。
  • 确认CloudFront允许传递查询参数(默认规则包含,但需后续配合缓存键配置)。

2. Lambda@Edge的核心作用

Lambda@Edge能在CloudFront边缘节点执行代码,主要解决两个问题:

  • 强化Next.js返回的Cache-Control头,确保CloudFront正确识别边缘缓存规则。
  • 自定义缓存键,让动态路由参数(如id)和查询参数(如powerlevel)成为缓存区分依据,避免不同请求共用缓存。

3. Lambda@Edge函数示例

(1)Origin Response触发器函数(修正缓存头)

该函数在CloudFront从源服务器拿到响应后执行,确保缓存规则符合边缘缓存要求:

exports.handler = async (event) => {
  const response = event.Records[0].cf.response;
  const headers = response.headers;

  // 保留Next.js设置的Cache-Control头,缺失则补充默认规则
  if (!headers['cache-control']) {
    headers['cache-control'] = [{
      key: 'Cache-Control',
      value: 'public, s-maxage=10, stale-while-revalidate=59'
    }];
  }

  // 移除私有缓存标记,确保响应可被CloudFront边缘节点缓存
  const cacheControlValue = headers['cache-control'][0].value;
  if (cacheControlValue.includes('private')) {
    headers['cache-control'][0].value = cacheControlValue.replace('private', 'public');
  }

  // 添加自定义缓存键标识,便于调试
  headers['x-cache-key'] = [{
    key: 'X-Cache-Key',
    value: event.Records[0].cf.request.uri + '?' + (event.Records[0].cf.request.querystring || '')
  }];

  return response;
};

(2)Viewer Request触发器函数(自定义缓存键)

如果需要强制CloudFront基于URI和查询参数生成缓存键,确保不同参数的请求缓存独立:

exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const uri = request.uri;
  const querystring = request.querystring;

  // 构建包含URI和查询参数的缓存键标识
  request.headers['x-cache-key'] = [{
    key: 'X-Cache-Key',
    value: uri + (querystring ? '?' + querystring : '')
  }];

  return request;
};

4. 部署与配置注意事项

  • Lambda@Edge函数必须部署在us-east-1区域,才能关联到CloudFront分发。
  • 在CloudFront缓存策略中,需设置基于请求URI和查询参数生成缓存键(或配合Lambda@Edge的自定义逻辑)。
  • 测试时可通过CloudFront的X-Cache响应头验证缓存命中情况(Hit from cloudfront表示命中边缘缓存)。
  • stale-while-revalidate规则生效逻辑:缓存过期后CloudFront先返回旧内容,后台异步刷新缓存,避免用户等待。

内容的提问来源于stack exchange,提问作者EternalObserver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:24:53