React Single SPA微前端部署新版本后仍加载旧脚本问题求助
解决Single SPA微前端部署后浏览器缓存旧代码的方案
1. 给打包资源添加内容哈希(核心方案)
浏览器缓存旧代码的核心原因是资源文件名未随内容更新,通过Webpack给输出文件添加内容哈希值,只要文件内容变化,文件名就会自动更新,强制浏览器加载新资源。
修改子应用(app-config)的Webpack配置
在合并的配置中添加output规则,同时更新字体资源的打包规则,给所有静态资源加上哈希:
module.exports = (webpackConfigEnv, argv) => { const defaultConfig = singleSpaDefaults({ orgName: "my-org", projectName: "my-app", webpackConfigEnv, argv, }); return merge(defaultConfig, { // 给JS/Chunk文件添加内容哈希 output: { filename: "[name].[contenthash].js", chunkFilename: "[name].[contenthash].chunk.js", }, resolve: { fallback: { "crypto": require.resolve("crypto-browserify"), "stream": require.resolve("stream-browserify") }, extensions: ['.ts', '.js', 'mjs', '.tsx'], alias: { src: path.resolve(__dirname, 'src'), } }, module: { rules: [ { test: /\.s[ac]ss$/i, use: [ "style-loader", "css-loader", "sass-loader", ], }, { test: /\.(woff|woff2|ttf|eot)$/, // 给字体文件也添加哈希,避免字体资源缓存 use: 'file-loader?name=fonts/[name].[contenthash].[ext]!static' } ] } }); };
修改根配置(root-config)的Webpack配置
根配置的HTML是整个应用的入口,需要确保它引用的资源路径带哈希,同时给自身输出文件加哈希,并禁止HTML文件被缓存:
module.exports = (webpackConfigEnv, argv) => { const orgName = "my-org"; const defaultConfig = singleSpaDefaults({ orgName, projectName: "root-config", webpackConfigEnv, argv, disableHtmlGeneration: true, }); return merge(defaultConfig, { // 给根配置的输出文件加哈希 output: { filename: "[name].[contenthash].js", }, plugins: [ new HtmlWebpackPlugin({ inject: false, template: "src/index.ejs", templateParameters: { isLocal: webpackConfigEnv && webpackConfigEnv.isLocal, orgName, }, // 添加meta标签,强制浏览器不缓存HTML文件 meta: { "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0" } }), ], }); };
2. 服务器端配置缓存策略
- 对于带哈希的静态资源(如
[name].[contenthash].js、字体文件):设置长期缓存(例如1年),因为文件名仅在内容变化时更新,无需担心缓存过期问题。 - 对于HTML文件和未加哈希的入口资源:设置
Cache-Control: no-cache, no-store, must-revalidate,强制浏览器每次请求都验证资源是否为最新版本。
3. 额外版本控制(可选)
如果需要更灵活的版本管控,可以在Single SPA注册子应用时,给资源URL添加动态版本参数(版本号可从后端接口获取):
// 在root-config的应用注册逻辑中 async function registerApps() { // 从后端接口获取最新版本号 const versionRes = await fetch('/api/latest-app-version'); const { version } = await versionRes.json(); registerApplication({ name: '@my-org/my-app', // 给子应用资源URL添加版本参数 app: () => System.import(`@my-org/my-app?version=${version}`), activeWhen: ['/my-app'], }); } registerApps();
内容的提问来源于stack exchange,提问作者Ryuzaki
相关产品推荐
相关产品推荐

