news 2026/9/11 4:53:48

如何用 verify-source-map 脚本验证 esbuild 生成的 sourcemap 正确性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用 verify-source-map 脚本验证 esbuild 生成的 sourcemap 正确性

如何用 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.jsreact。Makefile 里的scripts/node_modules目标就是cd scripts && npm ci

运行验证

主路径是在仓库根目录执行:

make verify-source-map

Makefile 中该目标实际依次做三件事:

  1. 依赖version-go:运行node scripts/esbuild.js --update-version-go,把version.txt的版本同步进cmd/esbuild/version.go(仅在内容不一致时修改该文件);
  2. 依赖scripts/node_modules:运行cd scripts && npm ci安装测试依赖;
  3. 运行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.gonpm/esbuild/package.json两个文件(仅当内容与version.txt不一致时),在仓库根目录生成esbuild可执行文件,并创建/删除scripts/.verify-source-map临时目录。

脚本具体校验什么

scripts/verify-source-map.js 中每个测试用例是一组脚本内置的小源文件(例如a.jsb-dir/b.jsb-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,);
  • 反向映射检查:对每个预置的检索串(如a0b0),先定位它在生成代码中的位置,再用SourceMapConsumer.originalPositionFor查回原始位置,要求sourcelinecolumn与它在原始源文件中的真实位置完全一致;
  • 正向映射检查:用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-4070issue-4075issue-4080issue-4104issue-4169等命名的用例)。其中complex用例会打包scripts/node_modules下的fuse.jsreact并校验其中的嵌套 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.jsout.js.map,对照sourcessourcesContentmappings手动核查,修复代码后重跑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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 4:52:25

RP2040看门狗完全解析:时钟、计数器、寄存器与喂狗实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 4:49:29

Linux Cgroups技术详解:资源隔离与容器化实践

1. Cgroups技术概述 Cgroups(Control Groups)是Linux内核提供的一种机制,用于限制、记录和隔离进程组使用的物理资源。这项技术最初由Google工程师在2006年提出,并于2007年合并到Linux 2.6.24内核主线中。它通过将进程分组并对其资…

作者头像 李华
网站建设 2026/9/11 4:45:06

从线上事故到生产实践:Redis核心原理与高可用架构全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华