因工作繁忙,差不多有三个月没有写过技术文章了,自八月份第一次编写 schematics 以来,我一直打算分享关于 schematics 的编写技巧,无奈还是拖到了年底。
Angular Schematics 是非常强大的一个功能,可以快速初始化项目,也可以自定义组件模板。在去年 schematics 发布以来,已经有部分开发者在项目中尝试使用,但是学习资料还是比较匮乏。目前官网已经有了 schematics 的简易教程,但在实际开发中仅靠官方教程还是会遇到很多问题。在开发 Ng-Matero 的过程中,编写 schematics 就像闯关一样,从 ng add 到 ng generate 再到 ng update,每个部分都耗费了博主大量的精力,翻阅了无数源码才得以实现。
在这个系列文章中,我将以 Ng-Matero 为例讲解 schematics 开发过程中遇到的难点,梳理开发流程,帮助大家开发自定义的 schematics 生成器。
该系列文章的三部分将分别介绍 Add、Generation 以及 Update,即使分了三部分来讲解 schematics,但我相信依然无法介绍的面面俱到。那遇到问题应该怎么办呢?没错,你需要看源码,这听起来可能让人心生畏惧,但是不用紧张,阅读源码并没有你想象的那么困难。顺便说一下,无论编写组件库还是 schematics,Angular Material 的源码都是最好的教材。
在继续阅读文章之前,请务必将官网的 Schematics 教程撸一遍,有关方法的说明可以参考 Schematics 的 README。
Add 的用途在我目前见过的项目中,ng add 主要有两个用途:
初始化组件库(比如 angular material, ng-zorro,ngx-bootstrap)
初始化项目模板(比如 ng-alain,ng-matero)。
初始化组件库相对简单一点,有些库的 ng add 甚至等同于 npm install。
相比之下,初始化项目模板要复杂很多,不仅要对项目进行配置,还要对项目中的文件进行增删改等操作。
本文将以初始化项目模板为例介绍 ng add 的执行过程。
Schematics 目录假设你的根目录有一个 schematics 的文件夹。
在官网的教程中,已经列出了 schematics 目录的两种风格:
1、你可以在 schematics 文件夹中单独安装 node_modules,这样你在 package.json 中定义 scripts 的时候逻辑会比较清晰,但是整个项目会有两套 node_modules,而大部分依赖都和根目录重复;
{ "scripts": { "build": "tsc -p tsconfig.json" }, }2、另外也可以复用根目录的 node_modules,这样的话就会减少不必要的安装了
{ "scripts": { "build": "../node_modules/.bin/tsc -p tsconfig.json" }, }使用 Angular CLI 来创建项目的话一般来说就是第一种情况,比如创建一个库或者创建一个 schematics,核心文件都会放在 src 目录。
注意:使用 Angular CLI 的默认目录对于 Generation 命令比较友好,Angular CLI 添加的默认路径为 src/app 或者 src/lib 等,如果我们修改了默认目录,则在使用 ng generate 命令时需要显式的设置 --path 参数。
发布 Schematics因为 schematics 就是一套执行脚本,所以在项目发布之前需要将 schematics 的编译文件复制到项目目录,否则也无法使用 schematics。
如果你开发的是一套组件库,那么你需要将 schematics 编译的文件拷贝到组件库中一起发布;
如果你开发的是一个项目模板,那么只需要发布 schematics 就可以了。
因为 schemaics 目录也是一个项目目录,所以你可以在 schematics 的 package.json 中定义拷贝命令,和官网教程是一样的,但是更恰当的方式应该是将复制命令写在根目录的 package.json 中。
{ "scripts": { "build:starter": "gulp --gulpfile gulpfile.js", "build:schematics": "npm run copy:schematics && cd schematics && npm run build && cd .. && npm run build:starter", "copy:schematics": "npm run clean:schematics && cpr schematics dist/schematics", "clean:schematics": "rimraf dist/schematics", } } 添加 ng add现在我们可以开始 ng add 的编写了,简单梳理一下,如果要使用 schematics 添加项目文件,我们需要做什么?
初始化项目的原始模板文件
删除 ng new 生成的重复文件(因为 schematic 无法自动替换文件)
把原始项目模板文件拷贝到项目目录
调整一下 package.json 和 angular.json
添加一些额外的 module
执行 npm install 安装 package
以下是 @angular/material 的 ng add 逻辑,ng-matero 与此类似。