Schematics 是前端開發工做流工具,例如:建立一個組件、變動配置項至當前項目。而且不限制任何語言環境;雖然如此,但 Schematics 目前依然只能依賴 Angular Cli 來運行相應的命令行。html
本文是在重構 ng-alain schematics 時閱讀 @angular-devkit
源碼的一些記錄;而關於 Schematics 的運用在知乎上有好幾篇不錯的文章,我將盡量跳開一些沒必要要的重複性工做,建議閱讀本文時能夠同下列文章一塊兒閱讀。前端
Schematics 一共包含四個指令:git
add
添加一個 Library 至項目new
建立一個新 Angular 項目generate
基於 Schematics 建立或修改文件update
更新應用程序或依賴項其實除了 add
會事先執行一次 npm i
(取決於 angular.json
的 cli/packageManager
配置值,默認:npm
)指令之外,其餘指令實際上都是基於 Schematics 建立或修改文件。github
generate
指令會更純粹,須要你手動指定 Schematic 名稱,例如:ng g class <ClassName>
。其餘三個指令是對其進一步簡化,像 ng add
實際至關於 ng g ng-add
這裏的 ng-add
是固定名稱,若你但願建立一個支持 ng add
那麼你就必須有一個 ng-add
的 Schematic。typescript
Schematics 執行核心的本質就是在維護一個很是大的 Observable 數據流,這裏的數據就是文件樹。npm
核心的主軸是執行一個 Schematics 時會在開始時構建一個虛擬文件系統 virtual-fs 就像 Rxjs 的 Observable
,後續的操做符都是對文件系統的變動動做,最後將虛擬文件系統的內容影射至物理文件中。json
一個 Schematics 能夠包含多個不一樣的指令,例如默認 Angular Schematics 有很是多咱們熟悉的 module
、component
等,而管理這些指令是經過 collection.json 配置項。工具
Schematics 建立完虛擬文件系統環境後,緊跟着依 collection.json 構建 Collection 對象,再根據指令中的名稱建立 Schematic 對象;而且調用並運行 Schematic Name 所對應目錄名下 index.ts
文件,例如一個 Schematic 完整的代碼結構:測試
function rule1() { return (host: Tree, context: SchematicContext) => { // doing }; } export default function(options: ApplicationOptions): Rule { return (host: Tree, context: SchematicContext) => { return chain([ rule1(), rule1() ]); } }
最終返回一個 Rule
類型,其本質是:命令行
(tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | void
若返回的是一個 Observable
類型時意味者這裏的空間變得無限大:
function rule1() { return (host: Tree, context: SchematicContext) => { return of(host); }; }
好比構建本身的遠程代碼片段庫。
Schematics 除了運行 Schematic 指令之外,還須要一些對項目進行額外操做,例如:安裝Node依賴包、初始化 Git 等。其實運行 Schematic 指令自己也是一種任務。這些任務是經過 SchematicContext
進行管理。
例如咱們但願在執行一個 Schematic 指令後調用一次 Node 依賴包的安裝,只須要調用內置的 NodePackageInstallTask
任務:
(host: Tree, context: SchematicContext) => { context.addTask(new NodePackageInstallTask()); }
angular.json 與 Schematic 有着很是密切的關係,大多數須要經過 angular.json 配置信息來獲取目錄路徑、默認配置項等信息。特別是當編寫 Schematic 時老是須要考慮多項目的狀況,所以絕大多數都須要依賴 angular.json 來確認具體項目名及路徑信息。
每個 Schematic 指令都有相應的參數信息,這些參數信息也能夠直接被映射在 angular.json 上面並當成默認參數值:
{ "schematics": { "ng-alain:list": { "spec": false }, "@schematics/angular:component": { "spec": false } } }
經過 ng g ng-alain:module <name>
(或 ng g component <name>
)生成時將忽略測試文件;固然對於這些默認參數的轉化都是 Schematics 內自動完成。
以上是一些簡單總結,Schematics 可玩性很是強,它是運行在一個 Node 容器內,所以可使用當下全部 Node 類庫。
而 Schematics 的操做除了文件之外,也會對文件內容進行修改,這一些也頗有意思。像 ts 文件能夠利用 typescript 類庫來獲取或調整 ts 文件內容某個變量名或值。而 html 文件能夠利用 parse5 來解析並修改,絕大多數文件類型均可以找到相對應的現有類庫來支持。
Schematics 只是 @angular-devkit
中的一小部分而已,還包括:Architect 用於改變 Angular cli 的運行機制,雖然本質上是在改變 Webpack 配置文件,但誰叫 Webpack 有着無限可能呢。
原先@angular-devkit
是做爲一個獨立的倉儲位於 @angular/devkit,然而不久前被合併入@angular-cli
裏。
(完)