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

如何在AWS负载均衡器后更新React应用避免main.js哈希变更致404

AWS CodeDeploy部署React应用的资源加载404问题解决

问题背景

我正在使用AWS CodeDeploy部署React应用,应用由npx create-react-app执行npm build构建生成,目录结构如下:

/var/www/my-website
.
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
    ├── css
    │   ├── main.2be1a5a0.css
    │   └── main.2be1a5a0.css.map
    ├── js
    │   ├── 787.28cb0dcd.chunk.js
    │   ├── 787.28cb0dcd.chunk.js.map
    │   ├── main.77918f81.js
    │   ├── main.77918f81.js.LICENSE.txt
    │   └── main.77918f81.js.map
    └── media
        ├── ...

生成的index.html核心内容:

<!doctype html>
<html lang="en">
   <head>
      <!-- 省略meta等基础配置 -->
      <title>React App</title>
      <script defer="defer" src="/static/js/main.77918f81.js"></script>
      <link href="/static/css/main.2be1a5a0.css" rel="stylesheet">
   </head>
   <body>
      <noscript>You need to enable JavaScript to run this app.</noscript>
      <div id="root"></div>
   </body>
</html>

EC2实例的Nginx配置:

server {
    listen       80;
    listen       [::]:80;
    server_name  _;
    root         /var/www/my-website;

    include /etc/nginx/default.d/*.conf;

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}

部署时的资源加载问题

当在AWS负载均衡器后使用in-place或blue/green部署方式时,新旧实例会共存一段时间(直到in-place部署完成或blue/green注销所有旧实例),此时会出现以下问题:

  • 请求路由到旧实例,返回包含旧哈希资源路径(如/static/js/main.hash1.js)的index.html
  • 浏览器通过负载均衡器发起资源请求,被分发到新实例
  • 新实例不存在该旧哈希资源,返回404错误

反向场景(先拿到新版本index.html,再请求旧资源)也会触发同样问题,只有所有请求命中同一版本实例时才能正常运行。

解决方案

1. 构建时使用相对路径,避免跨实例请求

修改项目根目录的package.json,添加homepage字段为./:

{
  "name": "my-react-app",
  "homepage": "./",
  // 其他项目配置字段...
}

重新执行npm run build,构建后的index.html中资源路径会变为相对路径:

<script defer="defer" src="./static/js/main.77918f81.js"></script>
<link href="./static/css/main.2be1a5a0.css" rel="stylesheet">

这样浏览器会从当前请求的实例加载资源,不会通过负载均衡器跨实例请求不同版本的资源。

2. 多版本资源保留+Nginx动态指向

  • 修改CodeDeploy部署脚本,将新版本部署到带版本标识的子目录,比如/var/www/my-website/v202405201200
  • 更新Nginx配置,将root指向最新版本的子目录,同时保留旧版本目录一段时间
  • 示例Nginx配置修改:
server {
    listen       80;
    listen       [::]:80;
    server_name  _;
    # 指向最新版本目录
    root         /var/www/my-website/v202405201200;

    include /etc/nginx/default.d/*.conf;

    # 可选:如果请求的资源在当前版本不存在,尝试从旧版本加载
    location ~* ^/static/ {
        try_files $uri /../v202405191000$uri =404;
    }

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}
  • 后续可通过定时任务清理超过7天的旧版本目录,避免磁盘占用过高。

3. 优化Blue/Green部署流程

  • 使用Blue/Green部署时,不要急于销毁蓝色(旧)环境实例,等待至少1-2个小时(根据用户会话时长调整)后再清理旧实例
  • 确保所有已加载旧版本index.html的用户都完成资源请求后,再删除旧环境的资源

4. 配置负载均衡器的会话粘性

  • 给负载均衡器开启会话粘性(粘性会话),让同一个用户的请求始终路由到同一个实例
  • 这样用户一旦加载了某个版本的index.html,后续资源请求都会命中同一个实例,避免跨版本资源请求问题
  • 注意:该方案仅适用于用户会话较短的场景,长期会话可能会导致用户无法及时获取新版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:31:20