如何用 verify-source-map 脚本验证 esbuild 生成的 sourcemap 正确性
【免费下载链接】esbuildAn extremely fast bundler for the web项目地址: https://gitcode.com/GitHub_Trending/es/esbuild
当你修改了 esbuild 自身与 sourcemap 相关的代码(或想确认某个构建出来的 esbuild 生成的 sourcemap 是否可信)时,仓库自带一个专门的验证脚本:scripts/verify-source-map.js,并接入了 Makefile 的verify-source-map目标。这个脚本会内置构造一批测试输入(JS 打包、CSS、TypeScript、stdin、代码拆分、unicode、第三方嵌套 sourcemap 等),用 Go 编译本地源码得到 esbuild 可执行文件后逐个运行并生成 sourcemap,再对映射逐项校验,全部通过时输出✅ verify source map passed。
准备条件
- 在 esbuild 仓库的工作副本中操作。脚本会编译
./cmd/esbuild、读取version.txt,临时目录创建在scripts/下,必须在仓库根目录运行。 - 已安装 Go:脚本内部调用
go build编译 esbuild 二进制(开发文档 中"编译 esbuild"一节同样以安装 Go 为前提)。仓库在 go.version 中记录了开发所用 Go 版本(当前为 1.26.5),check-go-version目标会在发布前核对它;verify-source-map本身不强制该版本,但建议保持一致。 - 已安装 Node:用于执行
npm ci和运行脚本。
脚本自身依赖在 scripts/package.json 中声明,关键是source-map(0.7.4,提供用来查映射的SourceMapConsumer),以及complex测试用例要打包的fuse.js和react。Makefile 里的scripts/node_modules目标就是cd scripts && npm ci。
运行验证
主路径是在仓库根目录执行:
make verify-source-mapMakefile 中该目标实际依次做三件事:
- 依赖
version-go:运行node scripts/esbuild.js --update-version-go,把version.txt的版本同步进cmd/esbuild/version.go(仅在内容不一致时修改该文件); - 依赖
scripts/node_modules:运行cd scripts && npm ci安装测试依赖; - 运行
node scripts/esbuild.js npm/esbuild/package.json --version(同样只在版本不一致时修改npm/esbuild/package.json),最后执行node scripts/verify-source-map.js。
没有make时也可以手动执行,效果等价(省略的只是前两条版本同步步骤,不影响映射验证本身):
cd scripts && npm ci cd .. node scripts/verify-source-map.js两种方式下,脚本都会先调用 scripts/esbuild.js 中的buildBinary():它在仓库根目录执行go build -ldflags=-s -w -buildid= -buildvcs=false -trimpath ./cmd/esbuild,生成esbuild可执行文件(Windows 上是esbuild.exe),后续所有测试用例都用它。也就是说,验证对象是你当前这份被修改过的源码,而不是任何已发布的二进制。
需要知晓的副作用:该流程会在你的本地检出中可能改写cmd/esbuild/version.go和npm/esbuild/package.json两个文件(仅当内容与version.txt不一致时),在仓库根目录生成esbuild可执行文件,并创建/删除scripts/.verify-source-map临时目录。
脚本具体校验什么
scripts/verify-source-map.js 中每个测试用例是一组脚本内置的小源文件(例如a.js→b-dir/b.js→b-dir/c-dir/c.js的多级导入链,或一个内联 base64 sourcemap 的单文件)。main()把每个测试用例按crlf(是否把换行改成 CRLF)与minify(是否追加--minify)的四种组合各跑一遍;每次调用 esbuild 时都带--sourcemap --log-level=warning,再叠加该用例专属参数(如--bundle、--outdir=. --bundle --splitting --format=esm、--jsx=automatic等)。每次运行都会做以下检查:
- 映射注释检查:输出文件必须含
# sourceMappingURL=...注释(stdin 用例则检查 stdout 中的内联sourceMappingURL=data:application/json;base64,); - 反向映射检查:对每个预置的检索串(如
a0、b0),先定位它在生成代码中的位置,再用SourceMapConsumer.originalPositionFor查回原始位置,要求source、line、column与它在原始源文件中的真实位置完全一致; - 正向映射检查:用
allGeneratedPositionsFor从原始位置反查生成位置,要求结果包含刚才那个位置; - sources 去重检查:sourcemap 的
sources数组不允许出现重复项; - 逐位置覆盖检查(仅非 bundle 模式):输出文件除 hashbang 行和 sourcemap 注释行外,每一行每一列都必须能映射到原始位置;
- 嵌套链式检查:把第一次的产物作为输入,另加一个
extra文件,按三种不同导入顺序再用--bundle --sourcemap --format=esm重新打包,并重复上述映射检查——这验证 esbuild 对已有 sourcemap 的链式重编码是否正确; - names 字段检查(专门的
checkNames流程):校验源码中以/**/标注的标识符名称(包括--mangle-props重命名后的属性名)能正确取出并往返一致。
测试用例类别覆盖:CommonJS/ES6 打包、不连续文件、TypeScript 运行时函数、stdin、空文件、非 JS 文件(.txt)、代码拆分、unicode 与--charset=utf8、含部分映射(partial mappings)的 sourcemap、CSS 打包、JSX automatic runtime、第三方工具(如 Clojure 的 shadow-cljs)生成的 indexed sourcemap、绝对路径、嵌套 sourcemap 中sourcesContent缺失或为 null 的情况,以及若干已知问题的回归(issue-4070、issue-4075、issue-4080、issue-4104、issue-4169等命名的用例)。其中complex用例会打包scripts/node_modules下的fuse.js与react并校验其中的嵌套 sourcemap,这也是npm ci必须装这两个依赖的原因。
如何判断结果
脚本最终只有两种输出:
- 全部通过:最后一行是
✅ verify source map passed,进程退出码为 0,临时目录scripts/.verify-source-map被删除; - 存在失败项:先逐条打印
❌ [测试用例名] 具体错误,最后一行是❌ verify source map failed,退出码为 1。
具体错误文案由脚本内的检查函数直接给出,用于定位问题,例如:
expected source: a.js, observed source: ...——映射查回的 source 不对;expected original position: {...}, observed original position: {...}——映射到的原始位置不对;expected generated position: ..., observed generated positions: [...]——正向映射结果不对;missing location for line 12 and column 5——非 bundle 模式下某生成位置完全没有原始位置;out.js file must link to out.js.map——输出中的映射注释不对;Duplicate source "..." found in source map——sourcemap 中 source 重复。
某个用例失败时,它在scripts/.verify-source-map下的临时目录不会被删除(通过的会删)。你可以直接打开对应用例目录里的输入文件、out.js与out.js.map,对照sources、sourcesContent和mappings手动核查,修复代码后重跑make verify-source-map。
与其他测试的关系
Makefile 中的注释标明verify-source-map属于test-common目标组(即make test会运行、面向开发阶段的测试)。只验证 sourcemap 行为时单独跑make verify-source-map即可;若需要完整开发测试(Go 测试、end-to-end 测试、JS API 测试等),再使用make test。
【免费下载链接】esbuildAn extremely fast bundler for the web项目地址: https://gitcode.com/GitHub_Trending/es/esbuild
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考