Webpack 的 stats 对象是分析打包过程和结果的核心数据来源。当需要查看某个模块经过 loader 处理、依赖解析后的最终代码时,默认的 stats 输出并不会携带源码内容。开启 stats.source 后,Webpack 会在统计信息的每个模块记录里增加 source 字段,从而把模块的源代码暴露出来。这个配置在 Webpack 4 和 Webpack 5 中都存在,默认值为 false。本文围绕它的配置方法、数据提取和性能影响展开。

一、stats.source 的作用与配置方式
stats.source 是 Webpack 统计输出中的一个布尔选项。它控制 stats 对象序列化时是否包含每个模块的源码字符串。默认情况下,source 为 false,因此 stats.toJson() 得到的 modules 数组里只包含模块名称、id、大小、依赖关系等元数据。开启后,Webpack 会尝试读取模块的源码内容,并写入对应模块的 source 字段。
在 webpack.config.js 中配置非常简单,只需在 stats 对象中设置 source: true。如果同时希望关闭其他统计信息以减少输出体量,可以配合 stats.all: false 使用。命令行方式同样支持,例如运行 npx webpack --stats-source,或者使用 --json=stats.json 输出统计文件后再解析。
// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
stats: {
all: false,
source: true,
},
};
上面的配置只输出与源码相关的统计字段,这样可以避免生成体积过大的 stats 对象。此时在终端运行 webpack --json > stats.json,生成的 JSON 中每个模块对象都会包含 source 属性。需要注意的是,开启 source 并不会影响最终打包产物,它只影响 stats 数据的内容。
二、通过 Node API 提取指定模块的源代码
除了使用命令行输出 JSON 文件,更常见的做法是在 Node 脚本中调用 Webpack 的 Node API,在编译完成后获取 stats 并遍历模块。这样可以按模块名称、路径或 id 精确提取源码,而不必解析庞大的 JSON 文件。
下面的代码启动一次 Webpack 构建,并在 run 回调中调用 stats.toJson({ source: true })。随后从 modules 数组中找到目标文件,打印它的 source 字符串。由于箭头函数和逻辑与在 HTML 代码块里需要转义,示例中已做处理。
const webpack = require('webpack');
const config = require('./webpack.config.js');
const compiler = webpack(config);
compiler.run((err, stats) => {
if (err) {
console.error(err);
return;
}
const json = stats.toJson({ source: true });
const targetModule = json.modules.find(
(mod) => mod.name && mod.name.includes('src/index.js')
);
if (targetModule) {
console.log('模块名称:', targetModule.name);
console.log('模块源码:');
console.log(targetModule.source);
} else {
console.log('未找到目标模块');
}
compiler.close(() => {});
});
运行该脚本后,控制台会输出 src/index.js 模块经过 loader 转换后的源码内容。这里需要注意,source 字段保存的是模块最终参与打包的代码,而不是磁盘上的原始文件内容。如果某个模块经过 Babel、TS 等 loader 处理,输出的将是转换后的 JavaScript 代码。对于 CSS 模块,source 可能不是最终注入 style 标签的字符串,而是该模块在打包流程中的代码表示。
另外,modules 数组中的元素不一定都是普通模块,还可能包含入口模块、容器模块等。建议在查找时同时判断 name 和 moduleType,避免误匹配。
三、stats.source 的性能影响与使用建议
开启 stats.source 最直接的影响是 stats 对象的体积会显著增大。对于包含数百个模块的中型项目,关闭时 stats JSON 可能只有几 MB,开启后可能膨胀到几十 MB 甚至更大。这是因为每个模块的完整源码都被序列化进统计结果,其中还包括 node_modules 里的第三方库代码。
这种体积增长不仅会占用内存,还会拖慢 stats 的序列化与输出速度。如果只是在 CI 中收集构建信息,建议保持 source: false。只有调试模块内容、排查 loader 处理结果或分析特定模块的打包代码时,才需要临时开启。为了减少开销,可以像前面示例那样设置 stats.all: false,只保留 source 和其他必要字段。
如果仅需要查看某个模块的源码,更精准的方法是使用 Webpack 插件机制,在编译过程中直接访问 compilation.modules,并调用模块对象的 originalSource() 或 source() 方法。这样避免了全量 stats 序列化,对构建性能的影响更小。下一节会给出一个自定义插件示例。
四、用自定义插件精准输出模块源码
在 Webpack 插件中,我们可以通过 compiler.hooks.done 钩子拿到最终的 stats 对象,然后只提取目标模块。这个方案比手动解析 stats JSON 更自动化,也更适合集成到开发工作流中。下面的插件会在构建完成后查找 src/index.js,并将源码写入项目根目录的 module-source.txt 文件。
class ExtractModuleSourcePlugin {
constructor(moduleName) {
this.moduleName = moduleName;
}
apply(compiler) {
compiler.hooks.done.tap('ExtractModuleSourcePlugin', (stats) => {
const json = stats.toJson({ source: true });
const target = json.modules.find(
(mod) => mod.name && mod.name.includes(this.moduleName)
);
if (target) {
const fs = require('fs');
fs.writeFileSync('module-source.txt', target.source);
console.log('源码已写入 module-source.txt');
}
});
}
}
module.exports = ExtractModuleSourcePlugin;
使用时只需在 plugins 里实例化该插件并传入要查找的模块名。这个插件仍然依赖 stats.toJson({ source: true }),但因为它只在 done 阶段执行一次,并且只保存一个模块的源码,所以整体开销可控。如果项目特别大,还可以在 done 钩子里先通过 compilation 对象直接遍历模块,而不是序列化整个 stats。
Webpack 5 的模块对象通常提供了 originalSource() 和 source() 方法,返回 Source 实例。在插件中可以通过 module.originalSource()?.source() 获取源码字符串。不过不同模块类型的 API 略有差异,使用 stats 输出仍然是最通用、最稳定的方式。
与 source map 相比,stats.source 给出的是编译后的模块代码,不包含源码映射关系;而 source map 可以还原原始文件的行列位置,适合在浏览器 DevTools 中调试。两者用途不同,排查模块内容时优先考虑 stats.source,定位线上错误时则使用 source map。
Webpack stats.source模块源代码stats 配置修改时间:2026-08-22 05:37:29