如何获取webpack输出文件列表并在PWA的service worker中使用
解决方案
问题根因
你当前导出了两个webpack配置数组,webpack会并行执行这两个配置的构建流程。frontend配置的资源清单要等整个构建流程收尾才会写入磁盘,而此时serviceworker配置的依赖解析步骤早就执行完了,自然找不到还未生成的page-files.json。第二次构建能成功是因为读取到了上一次构建残留的旧清单,会存在资源版本不一致的隐患。
方案1:调整构建顺序(最易改)
把两个配置拆分到独立文件,串行执行构建:
- 把原配置拆为
webpack.frontend.js和webpack.sw.js两个配置文件 - 修改package.json的构建脚本:
{ "scripts": { "build": "webpack --config webpack.frontend.js && webpack --config webpack.sw.js" } }
该方案可以复用你现有的导入逻辑,无需修改业务代码。
方案2:直接注入资源列表(最可靠)
通过DefinePlugin直接把资源列表注入到serviceworker代码中,完全避免读取磁盘文件:
修改后的webpack.config.js如下:
const path = require('path'); const webpack = require('webpack'); const WebpackAssetsManifest = require('webpack-assets-manifest'); // 存储页面资源列表 let pageAssets = []; const frontend = { mode: "development", entry: { page:"./src/page/page.tsx", }, devtool: 'inline-source-map', output: { path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.html?$|\.png$/, type: "asset/resource", generator: { filename: "[name][ext]", }, }, { test: /\.tsx?$/, loader: "ts-loader", exclude: /node_modules/, }, { test: /\.json$/, type: "asset/resource", exclude: /node_modules/, } ], }, resolve: { extensions: [".html", ".tsx", ".ts", ".js"], }, plugins: [ new WebpackAssetsManifest({ output: "page-files.json", writeToDisk: true, // 构建完成后把资源列表存入变量 done: (manifest) => { pageAssets = Object.values(manifest.toJSON()); } }), ] }; const serviceworker = { mode: "development", entry: { serviceworker: "./src/serviceworker/serviceworker.ts", }, devtool: 'inline-source-map', output: { path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.html?$|\.png$/, type: "asset/resource", generator: { filename: "[name][ext]", }, }, { test: /\.tsx?$/, loader: "ts-loader", exclude: /node_modules/, }, { test: /\.json$/, resourceQuery: /link/, type: "asset/resource", exclude: /node_modules/, }, { test: /\.json$/, resourceQuery: /str/, type: "asset/source", exclude: /node_modules/, } ], }, resolve: { extensions: [".html", ".tsx", ".ts", ".js"], }, plugins: [ // 把资源列表作为全局常量注入 new webpack.DefinePlugin({ PAGE_ASSETS: JSON.stringify(pageAssets) }) ] }; module.exports = [frontend, serviceworker];
然后直接在serviceworker.ts中使用常量即可,无需导入json文件:
console.log(PAGE_ASSETS);
方案3:使用workbox插件(最推荐)
workbox-webpack-plugin是webpack官方维护的PWA构建插件,会自动收集所有构建资源并注入到serviceworker中,无需自己维护资源清单逻辑,适配各种缓存策略,完全避免当前遇到的问题。
内容的提问来源于stack exchange,提问作者Colonel Thirty Two
相关产品推荐
相关产品推荐

