如何在Webpack 5中生成每个Chunk对应的源文件清单?
Webpack 5 生成Chunk与源文件映射清单方案
需求概述
在Webpack 5构建流程中,生成一份Chunk输出文件→对应源文件列表的映射清单,格式示例如下:
{ "app.930.59370e27f67ee1c4d4b8.js": [ "/src/components/Header.vue", "/src/utils/api.js" ], "vendor.123.abc.js": [ "/node_modules/react/index.js", "/node_modules/react-dom/index.js" ] }
要求直接在构建过程中获取类似sourcemap中sources字段的完整源文件信息,避免事后批量读取.map文件的低效方式。
已尝试的无效方案
webpack-assets-manifest/webpack-manifest-plugin:仅提供带哈希与不带哈希的文件路径映射,无法获取Chunk包含的源文件列表。- Webpack自带
recordsPath配置:仅记录触发Chunk拆分的文件(含import()的文件及直接导入文件),源文件信息不完整。
可行解决方案
方案:自定义Webpack插件
通过Webpack的编译钩子,在构建输出前直接收集Chunk与源文件的映射关系,生成目标清单并加入构建产物。
插件代码实现
创建ChunkSourceManifestPlugin.js文件:
const path = require('path'); class ChunkSourceManifestPlugin { constructor(options = {}) { this.outputFile = options.outputFile || 'chunk-source-manifest.json'; this.rootDir = options.rootDir || process.cwd(); // 项目根目录,用于路径转换 } apply(compiler) { // 在emit阶段(即将输出文件到磁盘前)执行逻辑 compiler.hooks.emit.tapAsync('ChunkSourceManifestPlugin', (compilation, callback) => { const manifest = {}; // 遍历所有编译生成的Chunk compilation.chunks.forEach(chunk => { // 遍历当前Chunk对应的所有输出文件(仅处理JS文件) chunk.files.forEach(file => { if (!file.endsWith('.js')) return; // 收集当前Chunk包含的所有源文件路径 const sourcePaths = []; chunk.modulesIterable.forEach(module => { // 跳过Webpack内部模块,仅处理有原始资源路径的模块 if (module.resource) { // 转换为相对于项目根的路径,或保留绝对路径 const relativePath = path.relative(this.rootDir, module.resource); // 如需绝对路径,替换为:const sourcePath = module.resource; sourcePaths.push(`/${relativePath}`); } }); // 去重后存入清单(避免重复模块) if (sourcePaths.length) { manifest[file] = [...new Set(sourcePaths)]; } }); }); // 将清单添加到构建输出资产中 compilation.assets[this.outputFile] = { source: () => JSON.stringify(manifest, null, 2), size: () => Buffer.byteLength(JSON.stringify(manifest, null, 2), 'utf8') }; callback(); }); } } module.exports = ChunkSourceManifestPlugin;
在Webpack配置中使用
修改webpack.config.js,引入并实例化插件:
const ChunkSourceManifestPlugin = require('./ChunkSourceManifestPlugin'); module.exports = { // ...其他Webpack配置项 plugins: [ // ...已有的插件 new ChunkSourceManifestPlugin({ outputFile: 'chunk-source-manifest.json', // 输出的清单文件名 rootDir: __dirname // 你的项目根目录,用于路径转换 }) ] };
关键说明
- 钩子选择:使用
compiler.hooks.emit钩子,确保在文件输出前完成数据收集,避免额外的文件读写操作。 - 模块过滤:通过
module.resource判断模块是否有原始源文件路径,可按需添加过滤规则(如排除node_modules中的依赖):// 示例:仅保留项目源码,排除node_modules依赖 if (module.resource && !module.resource.includes('node_modules')) { // ...收集逻辑 } - 路径处理:通过
path.relative将绝对路径转换为相对于项目根的短路径,也可直接保留绝对路径,根据需求调整。 - 异步Chunk支持:
compilation.chunks包含所有类型的Chunk(同步、异步),无需额外处理即可覆盖动态导入的Chunk。
内容的提问来源于stack exchange,提问作者RaphaelDDL
相关产品推荐
相关产品推荐

