Create React App PWA Service Worker缓存大小限制解决方案咨询
问题1:CRA自定义maximumFileSizeToCacheInBytes阈值的方法
无需eject项目,使用react-app-rewired或者craco覆盖CRA内置的Workbox配置即可实现,以react-app-rewired为例:
- 首先安装依赖:
npm i react-app-rewired workbox-webpack-plugin --save-dev - 项目根目录新建
config-overrides.js文件,加入以下配置:
const { InjectManifest } = require('workbox-webpack-plugin'); module.exports = function override(config, env) { if (env === 'production') { // 查找CRA内置的InjectManifest插件 const workboxPluginIndex = config.plugins.findIndex( plugin => plugin instanceof InjectManifest ); if (workboxPluginIndex !== -1) { const originalPlugin = config.plugins[workboxPluginIndex]; // 替换原有配置,修改最大缓存大小为12MB(可按需调整数值,单位为字节) config.plugins[workboxPluginIndex] = new InjectManifest({ ...originalPlugin.config, maximumFileSizeToCacheInBytes: 12 * 1024 * 1024, }); } } return config; };
- 修改package.json的scripts命令,把
react-scripts替换为react-app-rewired:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" }
修改后重新构建,所有小于12MB的静态资源都会自动加入预缓存清单,不会再触发大小告警。
问题2:避免手动维护带哈希的音频文件名
使用上述方案修改Workbox配置后,所有打包生成的带哈希音频文件会自动被注入到self.__WB_MANIFEST预缓存清单中,不需要手动维护文件名列表,每次音频文件更新后,打包时会自动生成新的哈希值同步到预缓存清单,完全不需要修改SW代码。
如果不想修改CRA的构建配置,也可以直接在现有SW代码中过滤出音频资源追加预缓存,无需手动写死文件名:
// 在precacheAndRoute调用前加入以下代码 // 从默认预缓存清单中过滤出所有mp3音频文件,追加到预缓存列表 const extendedManifest = self.__WB_MANIFEST.concat( self.__WB_MANIFEST.filter(entry => entry.url.endsWith('.mp3')) ); // 用扩展后的清单调用预缓存方法,同时传入自定义大小限制 precacheAndRoute(extendedManifest, { maximumFileSizeToCacheInBytes: 12 * 1024 * 1024 });
这个方案完全不需要修改构建逻辑,只需要修改SW代码即可实现音频资源的自动预缓存,不需要手动维护哈希文件名。
问题3:其他满足大音频预缓存、离线运行的方案
如果不希望把大音频加入安装时的预缓存(避免首次安装时加载体积太大、安装过慢),可以用运行时缓存+主动触发缓存的方案:
- 在SW中新增音频资源的路由规则,使用
CacheFirst策略:
registerRoute( ({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.mp3'), new CacheFirst({ cacheName: 'audio-cache', plugins: [ new ExpirationPlugin({ maxEntries: 20, // 按需调整最大缓存音频数量 maxAgeSeconds: 365 * 24 * 60 * 60, // 缓存1年 }), ], }) );
- 在应用首页加载完成后,主动请求所有需要离线使用的音频文件,触发缓存写入,不需要在SW安装阶段预缓存:
// 前端业务代码 const AUDIO_LIST = ['/static/media/song1.mp3', '/static/media/song2.mp3']; async function preCacheAudios() { if ('serviceWorker' in navigator) { for (const audioUrl of AUDIO_LIST) { await fetch(audioUrl); } console.log('所有音频缓存完成,可离线使用'); } } // 页面加载完成后调用 window.addEventListener('load', preCacheAudios);
这个方案可以避免首次安装PWA时下载过大的资源,用户打开应用后后台静默缓存音频,同样可以实现完全离线运行。
内容的提问来源于stack exchange,提问作者Francesco Cretti
相关产品推荐
相关产品推荐

