淺談Angular Cli Schematics

寫在前面

Schematics 是前端開發工做流工具,例如:建立一個組件、變動配置項至當前項目。而且不限制任何語言環境;雖然如此,但 Schematics 目前依然只能依賴 Angular Cli 來運行相應的命令行。html

本文是在重構 ng-alain schematics 時閱讀 @angular-devkit 源碼的一些記錄;而關於 Schematics 的運用在知乎上有好幾篇不錯的文章,我將盡量跳開一些沒必要要的重複性工做,建議閱讀本文時能夠同下列文章一塊兒閱讀。前端

指令類型

Schematics 一共包含四個指令:git

  • add 添加一個 Library 至項目
  • new 建立一個新 Angular 項目
  • generate 基於 Schematics 建立或修改文件
  • update 更新應用程序或依賴項

其實除了 add 會事先執行一次 npm i (取決於 angular.jsoncli/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 有很是多咱們熟悉的 modulecomponent 等,而管理這些指令是經過 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

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 裏。

(完)

相關文章
相關標籤/搜索