Angular CLI 6.x自定义Schematics构建正常却无法生成文件的问题排查
我来帮你搞定这个问题——Angular 6确实对Schematics的使用流程做了不少调整,尤其是集合的引用和配置逻辑,咱们一步步排查修复:
1. 先确认你的Schematics集合配置没问题
首先去my-first-schematics项目根目录,打开collection.json文件,确保里面正确注册了你的schematic。默认生成的配置大概是这样的:
{ "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "my-first-schematics": { "description": "A blank schematic.", "factory": "./my-first-schematics/index#myFirstSchematics" } } }
这里要注意:"my-first-schematics"是你集合里单个schematic的名称,而整个集合的名称是你package.json里的name字段(也就是my-first-schematics),别搞混了。
2. 修复本地测试的报错(步骤3的问题)
你之前执行schematics .:my-first-schematics报错,是因为默认生成的项目build后产物在dist目录,正确的本地测试命令应该指向build后的集合:
schematics dist:my-first-schematics
如果只是想验证逻辑不想真生成文件,可以加--dry-run参数:
schematics dist:my-first-schematics --dry-run
3. 解决CLI指定集合却仍找@schematics/angular的问题(步骤8的核心错误)
这个问题主要有两个原因,咱们逐个解决:
原因1:混淆了集合名和schematic名
你执行ng g my-schematic -c my-first-schematics的时候,首先你的集合里根本没有叫my-schematic的schematic(默认生成的是my-first-schematics),其次Angular 6 CLI更推荐用集合名:schematic名的格式来指定,比-c参数更可靠。所以正确的命令应该是:
ng g my-first-schematics:my-first-schematics
这里第一个my-first-schematics是你的集合名(也就是npm包名),第二个是集合里的schematic名称(对应collection.json里的key)。
原因2:确保npm link真的生效了
有时候npm link之后,Angular CLI可能没法正确解析集合,这时候可以试试两个办法:
办法一:在宿主项目的angular.json里配置集合
打开schematics-consumer的angular.json,添加集合配置:{ // 全局设置默认集合(可选) "cli": { "defaultCollection": "my-first-schematics" }, "projects": { "schematics-consumer": { // ...其他配置 "schematics": { "@schematics/angular": {}, "my-first-schematics": {} } } } }配置完之后,你直接执行
ng g my-first-schematics就能调用你的schematic了。办法二:用本地路径直接引用集合
如果link总是出问题,不如直接在schematics-consumer的package.json里加本地依赖:"devDependencies": { // ...其他依赖 "my-first-schematics": "file:../my-first-schematics" }然后执行
npm install,之后再用ng g my-first-schematics:my-first-schematics就能正常使用了。
4. Angular 6.x自定义Schematics的额外注意点
- 确保你的Schematics项目里
@angular-devkit/schematics的版本和宿主项目的CLI版本一致(你的环境里都是0.6.0,这点没问题)。 - 每次改完Schematics代码,一定要重新
npm run build,不然link的还是旧代码。 - 排查问题的时候可以加
--verbose参数,能看到更详细的日志:ng g my-first-schematics:my-first-schematics --verbose
内容的提问来源于stack exchange,提问作者Mickael Caruso

