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

基于Lambda@Edge实现单CloudFront+单S3 Bucket部署多React应用的问题排查

问题根源分析

你的Lambda@Edge函数现在犯了一个典型的SPA路由错误:它把所有进来的请求,不管是页面请求还是静态资源(CSS/JS/图片)请求,都强制重写到了index.html。这就导致浏览器请求static/css/main.xxx.css时,实际拿到的是index.html的内容,浏览器自然会因为MIME类型不匹配报错——毕竟它期望的是CSS,结果收到的是HTML文本。

解决方案:区分页面路由与静态资源请求

我们需要修改Lambda@Edge函数,让它只对需要SPA路由的请求(比如根路径、没有文件后缀的路径)返回index.html,而对静态资源请求,则保留原资源路径,只是加上对应的环境前缀(dev-test/sandbox-test/prod-test)。

修改后的Lambda@Edge代码

'use strict';
exports.handler = (event, context, callback) => {
    const cf = event.Records[0].cf;
    const request = cf.request;
    const origin = request.origin;
    const domain = request.headers.host[0].value;
    
    // 第一步:确定当前请求对应的环境前缀
    let envPrefix = '';
    if (domain.includes("dev")) {
        envPrefix = "/dev-test";
    } else if (domain.includes("sandbox")) {
        envPrefix = "/sandbox-test";
    } else {
        envPrefix = "/prod-test";
    }

    // 第二步:判断请求是页面路由还是静态资源
    const uri = request.uri;
    // 定义静态资源的后缀列表,可根据你的项目需求扩展
    const staticExtensions = ['.css', '.js', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.json'];
    const isStaticResource = staticExtensions.some(ext => uri.endsWith(ext));
    
    if (isStaticResource) {
        // 静态资源请求:给URI加上环境前缀
        request.uri = `${envPrefix}${uri}`;
    } else {
        // 页面路由请求:返回对应环境的index.html,适配SPA路由
        request.uri = `${envPrefix}/index.html`;
    }

    // 保持Host头修改,避免S3权限验证问题
    request.headers.host[0].value = origin.s3.domainName;
    
    return callback(null, request);
}

代码逻辑说明

  1. 环境前缀判断:和你原来的逻辑一致,根据Host头确定要指向的S3文件夹路径
  2. 静态资源识别:通过检查请求URI的后缀,区分出CSS/JS等静态资源请求
  3. 请求路由分支:
    • 静态资源:直接在原URI前加上环境前缀,比如/static/css/main.css变成/dev-test/static/css/main.css,确保S3返回正确的资源文件
    • 页面路由:不管是根路径/还是其他SPA路由(比如/about),都返回对应环境的index.html,保证SPA的前端路由能正常工作
额外检查项
  1. S3文件路径验证:确认你上传的React构建产物路径正确,比如dev-test文件夹下确实包含static/、index.html等所有build文件夹内的内容
  2. CloudFront缓存行为设置:确保你的CloudFront分发的Viewer Request事件已关联这个Lambda@Edge函数,且所有路径(/*)都触发该函数
  3. S3 MIME类型检查:S3通常会自动识别上传文件的MIME类型,但如果是批量上传,可确认下CSS/JS文件的Content-Type是否正确(比如CSS是text/css,JS是application/javascript)
  4. 测试验证:可以用curl命令测试静态资源请求,比如:
    curl -H "Host: dev.yourdomain.com" https://your-cloudfront-id.cloudfront.net/static/css/main.xxx.css
    
    查看返回内容是否是CSS代码,而非HTML。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 19:14:07