@puppeteer/ng-schematics 演进全解:从 Angular e2e 接入到多测试框架与 ESM 化的版本路线图
@puppeteer/ng-schematics 是 Puppeteer 仓库中用于把 Puppeteer 驱动的端到端(e2e)测试接入 Angular CLI 工程的官方 Schematic 集合,通过 ng add 一键安装并生成 utils.ts 等测试骨架,再以 ng e2e 启动 builder 完成「编译 → 启动 dev server → 运行测试」的闭环。本文以本仓库 packages/ng-schematics/CHANGELOG.md 的版本记录为时间主线,结合 README 与 schematics/builder 源码,系统梳理该包从 v0.1.0 到 v0.8.0 的能力演进、破坏性变更与工程化取舍。读完你将能够:判断哪个版本适合你的 Angular 工程(Node/TypeScript 兼容性)、完整配置 testRunner/port/baseUrl 等选项、在多应用工作区与单应用工程中正确接入,并理解底层 builder 的执行机制。
版本全览:一张表看懂八年演进主线
原始 changelog 以发布日志形式记录了每个版本的 Features / Bug Fixes / Breaking Changes。为便于检索,先将其核心内容整合为「版本 — 时间 — 关键变更」对照表:
| 版本 | 时间 | 关键变更 | 类型 |
|---|---|---|---|
| 0.1.0 | 2022-11-23 | 首次发布 @puppeteer/ng-schematics(PR #9244) |
新功能 |
| 0.2.0 | 2023-05-02 | 放弃 Node 14 支持 | Breaking |
| 0.3.0 | 2023-06-29 | 新增 Test 命令;port 选项支持 dev 与 e2e 并行;改用 Node test reporter |
新功能/修复 |
| 0.3.0 | 2023-08-02 / 08-03 | 支持多项目(multi projects)仓库 | 新功能 |
| 0.4.0 | 2023-08-08 | 正式落地多项目仓库支持 | 新功能 |
| 0.5.0 | 2023-08-22 | 精简用户选项、改进默认值;builder 负责解析命令;不为 library 项目安装 | 新功能/修复 |
| 0.5.1 | 2023-11-13 | 多应用工程扩展根 tsconfig.json;支持 Angular 17 新模板 |
修复 |
| 0.5.2 | 2023-11-16 | 运行 post-install 钩子 | 修复 |
| 0.5.3 | 2023-12-04 | 修复 Windows 下的安装问题 | 修复 |
| 0.5.4 | 2023-12-06 | 从已创建的 server 读取端口 | 修复 |
| 0.5.5 | 2023-12-19 | 更新 ng-schematics 文档 | 文档 |
| 0.5.6 | 2024-01-16 | 修复 Windows 下 jest 配置问题 | 修复 |
| 0.6.0 | 2024-02-05 | 放弃 Node 16 支持 | Breaking |
| 0.6.1 | 2024-06-20 | 默认 tsconfig 采用 NodeNext 模块解析 | 修复 |
| 0.7.0 | 2024-09-11 | 支持自定义 baseUrl(PR #12928) |
新功能 |
| 0.8.0 | 2026-05-12 | 包全面迁移到 ESM only;最低 Node 22;文档更新 Node v20.19 + TypeScript v5.0.1 | Breaking |
说明:其中 0.3.0 存在三次同名发布(含两次重复记录的多项目支持条目),0.4.0 是同一能力的正式收敛,本表按功能归属去重合并;其余条目与原 CHANGELOG.md 一一对应,未增删事实。
快速上手:add → generate → e2e 三步走
无论版本如何演进,「把 Puppeteer e2e 装进 Angular 工程」的入口始终统一。在任意 Angular CLI 应用目录下执行:
ng add @puppeteer/ng-schematics
该命令会把 schematic 作为依赖写入工程(package.json 中声明的 "ng-add": {"save": "devDependencies"} 与之一致),并进入交互式提问选择测试框架。安装完成后直接运行:
ng e2e
支持的测试框架与 --test-runner 选项
当前版本(0.8.0)支持四种测试框架。安装时通过 --test-runner 显式指定(必填),可用值如下表:
| 选项 | 说明 | 取值 |
|---|---|---|
--test-runner |
与 Puppeteer 一同安装的测试框架 | "jasmine"、"jest"、"mocha"、"node" |
这是 README 中 ng-add 唯一的用户级选项。其取值约束直接定义在 ng-add 的 schema.json 中:
enum限定为["jasmine", "jest", "mocha", "node"];default为"jasmine",不指定时走 Jasmine;- 配置了
x-prompt的列表交互,ng add时由 CLI 弹出框架选择清单; - 别名
"t",因此也可以写作ng add @puppeteer/ng-schematics --test-runner jest。
值得注意:changelog 0.3.0 曾专门修复「port 选项支持 dev 与 e2e 并行」并引入 Node Test Runner(对应条目“use Node test reporter”)。到 0.8.0,四种框架已被视为一等公民,builder 层对每种框架做了命令级映射(详见下文)。
创建单个测试文件
除整体安装外,还可用内置的 e2e schematic 只生成单个 spec:
ng generate @puppeteer/ng-schematics:e2e "<TestName>"
从 e2e 的 schema.json 可看到其参数设计:name(测试名,-n)取自命令行第 0 个参数,project(-p)与 route(-r)取自第 1 个参数;若 route 以 / 开头,源码 e2e/index.ts 会自动去掉前缀,保证生成的路由写法统一。
运行时架构:三个 schematic + 一个 builder
ng-schematics 不是单一脚本,而是「collection(schematic 入口)+ architect builder(测试执行器)」的组合。清单 collection.json 声明了三个 schematic:
ng-add:向 Angular 工程注入 Puppeteer 依赖、公共文件与测试框架文件,并改写angular.json;e2e:生成单个测试文件(上节已述);config:把 Puppeteer 配置「弹射(eject)」到工程中(其 schema 目前无参数)。
package.json 中把两个入口分别指向 ./lib/schematics/collection.json 与 ./lib/builders/builders.json,这是 Angular CLI 发现 schematic 与 builder 的约定位置。
ng-add 的执行链(chain)
ng-add/index.ts 把整个安装过程编排为一条 chain,先后执行五个规则:
addDependencies—— 查询依赖最新 npm 版本并写入package.json,同时注册NodePackageInstallTask,且显式开启allowScripts: true以触发 post-install 钩子下载浏览器(这正是 0.5.2 “run post-install hooks” 的源码落点);addCommonFiles—— 写入与测试框架无关的公共文件,端口默认取常量DEFAULT_PORT = 4200;addOtherFiles—— 按所选框架写入对应配置(jasmine/jest/mocha/node 各自目录);updateScripts—— 单应用工程在package.json写入e2e/test脚本(多应用工程则改写为ng run <project>:...形式);updateAngularConfig—— 更新angular.json中的 architect 目标。
其中一处细节直接呼应 changelog:当工程存在多应用时,updateScripts 会拼接 run <projectName>: 前缀,对应 0.3.0/0.4.0 的「multi projects repos」支持;而 0.5.0 的 "don't install for library projects" 则体现在 getApplicationProjects 只筛选 application 类工程。
builder:测试到底如何被执行
真正跑 ng e2e 的是 architect builder @puppeteer/ng-schematics:puppeteer。其核心实现见 builders/puppeteer/index.ts,执行序列是:
- 先执行
tsc -p e2e/tsconfig.json编译测试 TS; - 调用
getServerAndUrl:若配置了baseUrl则不再拉起 server;否则按devServerTarget调度 Angular dev server; - 通过
getCommandForRunner按testRunner映射出最终命令并spawn执行; - 结束后停掉 server,返回
{success}供 Angular CLI 汇总。
getCommandForRunner 对四种框架的命令映射可直接查阅源码,且与「0.5.0 之后 builder 负责解析命令」这一修复一一对应:
| testRunner | 实际执行的命令 |
|---|---|
| Jasmine | jasmine --config=./e2e/jasmine.json |
| Jest | jest -c e2e/jest.config.js |
| Mocha | mocha --config=./e2e/.mocharc.cjs |
| Node | node --test --test-reporter spec e2e/build/**/*.e2e.js |
注意 Node Test Runner 分支不经过 node_modules/.bin,直接使用系统 node——这正是 0.5.0 修复「builder 负责解析命令」与早期 Windows 安装问题(0.5.3、0.5.6)反复打磨的结果;命令解析时的可执行文件路径由 updateExecutablePath 依据工程 root 深度回退计算,保证多应用嵌套目录也能找到本地 bin。
关键配置项:端口、dev server 与 baseUrl 的演进
builder 的合法选项定义在 builders/puppeteer/schema.json,四个属性恰好串起 changelog 中的几段历史:
| 属性 | 类型 | 含义 |
|---|---|---|
commands |
string[][] |
在仓库中执行的命令;除 node 外,以 ./node_modules/bin 前缀解析 |
devServerTarget |
string |
负责拉起 dev server 的 Angular target(如 sandbox:serve) |
port |
number | null |
测试 server 的运行端口 |
baseUrl |
string | null |
直接指定测试目标 URL;一旦提供则不再拉起 server |
dev 与 e2e 并行(0.3.0 引入的 port)
默认情况下 e2e 复用 ng serve 的同一端口,容易冲突。README 给出标准做法:在 angular.json 的 e2e(或早期版本的 puppeteer)目标中覆盖端口:
{
"e2e": {
"builder": "@puppeteer/ng-schematics:puppeteer",
"options": {
"commands": [],
"devServerTarget": "sandbox:serve",
"testRunner": "<TestRunner>",
"port": 8080
}
}
}
随后把测试文件 utils.ts 中的 baseUrl 改为对应地址:
const baseUrl = 'http://localhost:8080';
源码侧,builders/puppeteer/index.ts 的 startServer 会通过 targetFromTargetString 解析 devServerTarget,读取目标默认参数后以 watch: false、port: options.port ?? 默认端口 的 override 重新调度 server——0.5.4 “get port from created server” 的意图即在于保证返回给测试的 baseUrl 来自真正监听中的 server 而非配置文件里的静态值。
自定义 baseUrl(0.7.0 新能力)
0.7.0 的「support custom baseUrl」在运行时表现为 getServerAndUrl 的最短路判断:一旦 options.baseUrl 非空,直接以该 URL 作为测试目标并跳过整条 server 启动链路。其适用场景是:被测应用已由外部部署(CI 预置环境、容器、独立 dev server),无需 Angular builder 代为拉起。这也让 baseUrl 与 devServerTarget 形成互斥双通道:
- 配
devServerTarget(+可选port)→ builder 自行启停 server; - 配
baseUrl→ builder 只编译测试并执行,不再管理 server 生命周期。
Node / TypeScript 版本门槛:一场持续的收敛
changelog 中最连续的演进主线是运行环境下限的抬升,它对升级路径有直接指导意义:
- 0.2.0(2023-05):Breaking —— drop support for node14,Node 16 成为下限;
- 0.6.0(2024-02):Breaking —— drop support for node16;
- 0.6.1(2024-06):默认生成的
e2e/tsconfig.json改用 NodeNext 模块模式,为 ESM 化铺路; - 0.8.0(2026-05):Breaking 三连 —— 包整体迁移到 ESM only;最低 Node 升到 22;文档同步更新为 Node v20.19 + TypeScript v5.0.1 的下限(后两条以 Documentation 条目记录)。
以上门槛与当前 package.json 完全吻合:"type": "module"、"engines": {"node": ">=22.12.0"}。这意味着若你的 Angular CI 仍运行在 Node 16/18 上,请锁 ≤0.5.x/0.6.x 的兼容版本;若跟随最新版,则必须保证 Node ≥ 22.12.0。
面向真实工程的多应用与生态兼容
从 changelog 的 Bug Fixes 序列,可以提炼出接入大型/多应用 Angular 工程时的四个避坑点:
- 多应用工作区(0.3.0/0.4.0):
ng add与ng generate都会遍历angular.json中的应用工程,e2eschematic 会依据工程数量或--project参数选定目标工程,未命中时抛出带提示的SchematicsException。单应用工程的脚本写作ng e2e,多应用则写作ng run <app>:e2e。 - 多应用根 tsconfig 继承(0.5.1):修复了嵌套项目无法正确 extend 根
tsconfig.json的问题,保证编译测试时类型与路径别名一致;同版本还适配了 Angular 17 全新的 workspace 模板。 - library 工程豁免(0.5.0):安装器只对 application 类工程生效,不会污染库工程的依赖与脚本。
- 平台差异(0.5.3 Windows 安装、0.5.6 Windows jest 配置、0.6.1 NodeNext):Windows 上的
node_modules/.bin解析、jest 配置文件路径均有过针对性修复,跨平台团队建议优先使用 ≥0.5.6 版本。
测试文件模板与 Protractor 迁移指引
ng add 生成的公共文件位于 ng-add/files/common/e2e/,其中包括供测试使用的 utils.ts 与 tsconfig.json 模板;单测模板文件名带有 __name@dasherize__ 占位符,Angular 会将其替换为实际测试名,Node Test Runner 分支的扩展名被固定为 .test.ts(源码注释说明:Node 原生测试不支持 glob 模式,按 *.test.js 查找),其余框架为 .e2e.ts。
对从 Protractor 迁来的团队,README 的 "Migrating from Protractor" 是权威对照。核心要点是:Protractor 的全局 browser 更接近 Puppeteer 的 page(Puppeteer 的 browser 仅暴露浏览器进程本身)。测试骨架统一从 utils.ts 引入:
import {setupBrowserHooks, getBrowserState} from './utils';
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements
await page
.locator('my-component')
.click();
});
});
选择器对照(Protractor By → Puppeteer):
| 语义 | Protractor | Puppeteer |
|---|---|---|
| CSS(单个) | $(by.css('<CSS>')) |
page.$('<CSS>') |
| CSS(多个) | $$(by.css('<CSS>')) |
page.$$('<CSS>') |
| 按 id | $(by.id('<ID>')) |
page.$('#<ID>') |
| 文本包含 | by.cssContainingText('<CSS>','<TEXT>') |
page.$('<CSS> ::-p-text(<TEXT>)') |
| 穿透 Shadow DOM | by.deepCss('<CSS>') |
page.$(':scope >>> <CSS>') |
| XPath | by.xpath('<XPATH>') |
page.$('::-p-xpath(<XPATH>)') |
| 任意 JS 表达式 | by.js(...) |
page.evaluateHandle(() => ...) |
交互动作也有一一对应关系:click() → await page.locator(l).click();sendKeys() → fill();clear() → fill('');读取属性用 waitHandle() + getProperty()。完整迁移示例见 README 的 Protractor/Puppeteer 双侧代码对比。
开发与验证:单测与 smoke 冒烟
本包的自身质量验证方式对使用者也具有参考价值:
- 冒烟测试:
node tools/smoke.mjs会新建单应用与多应用两类全新 Angular 工程,装入 schematics 后运行首轮 e2e,用于验证与最新版 Angular CLI 的集成是否仍然成立,参见 tools/smoke.mjs; - 单元测试:schematics 依赖
@angular-devkit/schematics/testing断言文件生成与package.json改写是否正确。测试源码位于 test/src(ng-add.test.ts、e2e.test.ts、config.test.ts),npm run test实际经由 wireit 编排:先tsc编译测试,再以 Node 原生 test runner 执行test/build/**/*.test.js(可参见 package.json 的 scripts/wireit 段)。
升级建议小结
综合 changelog 与当前仓库事实(版本 0.8.0):
- 新工程、Node ≥ 22.12:直接用最新版,
--test-runner四选一,配合port或baseUrl即可运行; - 存量工程仍在 Node 16:最高只能升到 0.5.x(0.6.0 起移除 Node 16);Node 18/20 场景选择 0.6.x~0.7.x,注意 0.8.0 起包已完全 ESM only,CommonJS 工程需同步调整;
- 多应用、Angular 17+、Windows 团队:建议 ≥ 0.5.6(0.6.1 修复了 NodeNext tsconfig 问题);
- 面向已部署环境测试:0.7.0 起启用自定义
baseUrl可省去 dev server 生命周期管理,是最贴合 CI 的配置方式。
版本之间的每一个特性、修复与破坏性变更都可在 CHANGELOG.md 中回溯,并在 packages/ng-schematics 的源码与测试里找到对应实现,可作为团队评估与升级的原始依据。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00