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

React+Vite部署Cloud Run后每次更新出现脚本加载失败问题求助

解决Vite+React部署Cloud Run后浏览器缓存旧资源导致的加载错误

问题现象

使用Vite构建React应用,通过Github Actions自动部署到Cloud Run后,每次新版本上线,带随机哈希的脚本文件(如index-XXX.js)会更新,但之前访问过应用的浏览器会尝试加载旧的哈希脚本,引发两类错误:

  • Expected a Javascript module script but the server responded with a MIME type of "text/html"
  • 提示无法找到已不存在的旧脚本文件

硬刷新(F5/Cmd+R)可临时解决,但用户体验差,需要永久修复。

问题根源

核心原因是浏览器缓存了旧的index.html文件:
Vite生产构建会给静态资源添加内容哈希,资源更新后哈希自动变更,但作为入口的index.html没有哈希标识,浏览器会默认缓存它。当新版本部署后,旧的index.html仍会引导浏览器请求已被删除的旧哈希脚本,Nginx返回404页面(HTML类型),从而触发MIME类型错误;或直接返回404找不到文件。

解决方案

1. 配置Nginx缓存策略(关键)

修改nginx.conf,对index.html设置禁止缓存,对带哈希的静态资源设置长期缓存:

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    # 对带哈希的静态资源设置长期缓存(内容不变则永久有效)
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }

    # 强制index.html不被缓存,每次请求都拉取最新版本
    location = /index.html {
        expires -1;
        add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
    }

    # SPA路由 fallback,避免单页应用刷新出现404
    location / {
        try_files $uri $uri/ /index.html;
    }
}

2. 确认Vite构建配置有效性

当前vite.config.ts无需额外修改:Vite默认在生产构建时会给静态资源添加内容哈希,现有manualChunks配置仅影响代码分割逻辑,不影响哈希生成,保持当前配置即可。

3. Cloud Run部署补充

确保每次部署使用唯一镜像标签(当前Github Actions已用$GITHUB_SHA作为标签,满足要求),保证Cloud Run部署全新实例。同时,Nginx设置的Cache-Control响应头会被Cloud Run传递给客户端,无需额外配置Cloud Run的缓存规则。

4. 进阶:添加版本主动检测(可选)

若想主动提示用户应用更新,可在应用中加入版本检测逻辑:

  • 步骤1:注入版本号到应用
    修改vite.config.ts,将package.json中的版本号注入应用:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
import pkg from './package.json';

export default defineConfig({
  define: {
    '__APP_VERSION__': JSON.stringify(pkg.version),
  },
  // 其他原有配置...
});
  • 步骤2:生成版本检测文件
    修改Dockerfile的build阶段,在dist目录生成version.json:
# BUILD阶段末尾添加
RUN node -e "const pkg = require('./package.json'); require('fs').writeFileSync('./dist/version.json', JSON.stringify({version: pkg.version}));"
  • 步骤3:应用内检测版本
    在根组件中添加版本检测逻辑:
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    async function checkVersion() {
      try {
        const res = await fetch('/version.json');
        const data = await res.json();
        if (data.version !== __APP_VERSION__) {
          alert('应用已更新,请刷新页面');
          // 也可自动刷新:window.location.reload(true);
        }
      } catch (e) {
        console.error('版本检测失败', e);
      }
    }
    checkVersion();
    // 每小时检测一次版本
    const interval = setInterval(checkVersion, 3600000);
    return () => clearInterval(interval);
  }, []);

  return <div>你的应用内容</div>;
}

总结

通过Nginx配置正确的缓存策略是解决问题的核心,确保index.html不被缓存、哈希资源长期缓存即可彻底解决加载错误。进阶的版本检测机制可进一步提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 22:27:44