webpack 5 如何用 extractSourceMap 规则提取第三方库的 source map 并映射回源文件
【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack
当你引入一个第三方库时,node_modules里通常只有编译后的 JS 文件,真正的源文件(比如 TypeScript 源码)并不直接暴露给构建工具。如果打包产物中第三方库的代码只是指向编译后的index.js,调试或查看代码时看到的就不是原始源码。webpack 5 提供了extractSourceMap这条 module rule:当库自带的.map文件指向其源文件时,webpack 会读取该映射,让最终产物的 source map 直接引用库的原始源文件。schemas/WebpackOptions.json中对该配置的定义是Enable/Disable extracting source map,类型为boolean。
下面基于仓库中的 source-mapping-url 示例 说明完整的配置、构建和核对方式。
示例演示的第三方库结构
examples/source-mapping-url/README.md 用一个library包模拟了典型第三方库的形态:
- 源文件
node_modules/library/src/index.ts(TypeScript 源码); - 编译产物
node_modules/library/lib/index.js,文件末尾带有//# sourceMappingURL=index.js.map; - 映射文件
node_modules/library/lib/index.js.map,其sources字段为"../src/index.ts",即映射回 TypeScript 源文件。
示例的入口 example.js 只是导入并调用该库:
import { greet } from "library"; // Valid value console.log(greet("world")); // Wrong value console.log(greet(128));这种"编译产物 +sourceMappingURL+ 指向源文件的.map"结构,就是extractSourceMap规则要处理的目标。
配置 extractSourceMap 规则
示例的 webpack 配置 如下:
"use strict"; /** @type {import("webpack").Configuration} */ const config = { mode: "development", devtool: "source-map", module: { rules: [ { test: /\.js$/i, extractSourceMap: true } ] } }; module.exports = config;各部分的作用:
devtool: "source-map":让 webpack 为打包产物生成独立的 source map 文件。没有这一项,产物本身不会输出.map,也就谈不上把第三方库映射回源文件;test: /\.js$/i:规则匹配所有.js模块,即第三方库中编译后的 JS 文件;extractSourceMap: true:对命中的模块启用 source map 提取,读取模块自带映射中指向的源文件内容。
构建示例
仓库文档给出在示例目录下构建的完整步骤(见 examples/README.md 的 "Building an Example" 一节):
# 在项目根目录 yarn yarn setup yarn add --dev webpack-cli # 进入具体示例目录后构建 cd examples/source-mapping-url && node build.js如果需要构建所有示例,文档给出的命令是npm run build:examples。注意该命令会构建全部示例,不是只构建当前这一个;本文只需要构建 source-mapping-url,使用上面的node build.js路径即可。
核对结果:产物映射回了库的源文件
构建后检查dist目录的两个文件:
dist/output.js末尾带有//# sourceMappingURL=output.js.map,说明产物关联了独立的 source map;- 打开
dist/output.js.map,核对sources数组。README 中记录的示例输出 里,sources包含:
"sources":["webpack:///./node_modules/library/src/index.ts", ...]同时sourcesContent中保存了对应的原始 TypeScript 源码(const greet = (name: string) => { ... }那段源文件内容),而不是编译后的 JS。这说明产物 source map 已经越过lib/index.js这一层编译产物,直接指向了库的源文件node_modules/library/src/index.ts。
示例 README 还记录了两种模式下的构建统计(以下为文档示例输出):
Unoptimized 模式:
asset output.js 3.06 KiB [emitted] (name: main) 1 related asset chunk (runtime: main) output.js (main) 407 bytes (javascript) 211 bytes (runtime) [entry] [rendered] > ./example.js main dependent modules 289 bytes [dependent] 1 module runtime modules 211 bytes 1 module ./example.js 118 bytes [built] [code generated] [no exports] [used exports unknown] entry ./example.js main webpack X.X.X compiled successfullyProduction 模式下产物被压缩,但仍有1 related asset,即 source map 文件照常生成。
边界与实现位置
extractSourceMap只是一个布尔开关,挂在 module rule 上按test/include等条件匹配模块生效,配置方式与sideEffects、parser等其他规则设置同级,定义见 schemas/WebpackOptions.json;- 规则能否映射回源文件,取决于第三方库自身是否提供了正确的
sourceMappingURL和.map(其sources要指向源文件)。示例中lib/index.js.map的"sources":["../src/index.ts"]就是这一前提; - 仓库中的示例目录只提交了
README.md、example.js、template.md和webpack.config.js,node_modules/library与dist的完整内容记录在 README.md 中,核对输出时以该文档为准; - 实现上,
extractSourceMap设置通过 lib/NormalModuleFactory.js 进入模块,提取逻辑位于 lib/util/extractSourceMap.js。
【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考