爲了讓 Angular 類庫應用範圍更自由,Angular 提出一套打包格式建議名曰:Angular Package Format,包括 FESM201五、FESM五、UMD、ESM201五、ESM五、ES2015 格式,不一樣格式能夠在不一樣的環境(Angular Cli、Webpack、SystemJS等)中使用。node
傳統方式須要對這些格式逐一打包,一個示例打包腳本寫法。這種寫法只能針對不一樣項目的配置,並且除非你瞭解這些格式的本質不然很難維護;後來社區根據 APF 規範實現了類庫 ng-packagr,經過簡單的配置能夠將你的類庫打包成 APF 規範格式。git
至 V6 之後 Angular Cli 也基於 ng-packagr 實現了另外一個 @angular-devkit/build-ng-packagr 應用構建器。github
既然 ng-packagr 被 Angular Cli 內置,這讓咱們進一步簡化了生產一個 APF 規範格式的類庫的成本。在 Angualr Cli 裏使用 ng g library
來建立一個類庫模板,例如在一個新的 Angular 應用裏執行:npm
ng g library <library name>
而打包,則:json
ng build <library name>
最終,將生成的 dist/<libary name>
目錄下文件上傳相應包管理服務器(例如:npm)提供給其餘 人使用。bootstrap
由 Angular Cli 生成的類庫模板大部份內容同 Angular 應用同樣,只是多了一個 ng-package.json
的配置文件(對於生產環境是 ng-package.prod.json
),它是專門針對 ng-packagr 的一個配置文件,如同 angular.json 通常也是基於 JSON Schema 格式,所以能夠經過訪問 ng-package.schema.json 瞭解全部細節,如下描述一些重點項。api
whitelistedNonPeerDependenciesbash
ng-packagr 默認會根據 package.json 的 peerDependencies
節點清單來決定類庫所須要第三方依賴包,這些依賴包是不會被打包至類庫。服務器
然而,所依賴包不存在 peerDependencies
節點裏時(固然建議須要依賴的項應該在裏面),就須要該屬性的配置。測試
lib/entryFile
指定入口文件。
lib/umdModuleIds
UMD 格式採用 rollup 打包,當類庫須要引用一些沒法猜出正確 UMD 標識符時,就須要你手動映射這些類庫的標識。
"umdModuleIds": { "lodash": "_" }
angular.json
Angular Cli 配置文件 angular.json 內會增長一個以 <libary name>
命名的構建配置,絕大多數配置性同普通 Angular 應用一模一樣,惟一不一樣的是 builder
節點爲:
"builder": "@angular-devkit/build-ng-packagr:build"
有時候一個類庫可能會包含着多個二次入口,就像 @angular/core
類庫包含着一個 @angular/core/testing
模塊,它只是運用於測試,所以並不但願在項目中引入 @angular/core
時也包含測試代碼,但同時兩者又是同一個功能性時,這種次級導入顯得很是重要。
另外一種像 ngx-bootstrap、@angular/cdk/ally 等都提供次級模塊的導入,能夠更好的優化體積。
不論出於何種目的,均可以經過 Angular Cli 簡單的文件組織進一步打包出主、次級分明的類庫。
ng g library
生成的結構大概以下:
<libary name> ├── src | ├── public_api.ts | └── lib/*.ts ├── ng-package.json ├── ng-package.prod.json ├── package.json ├── tsconfig.lib.json └── tsconfig.spec.json
當根目錄下包含README.md
、LICENSE
時會自動被複制到dist
目錄中,Npm 規定必須包含 README.md 文件,不然訪問已發佈類庫頁時會有未找到描述文件錯誤提示。
若想建立一個 <libary name>/testing
的次級入口,只須要在 <libary name>
根目錄下建立一個 testing
目錄:
<libary name> ├── src | ├── public_api.ts | └── lib/*.ts ├── ng-package.json ├── ng-package.prod.json ├── package.json ├── tsconfig.lib.json ├── tsconfig.spec.json └── testing ├── src | ├── public_api.ts | └── *.ts └── package.json
核心是須要提供一個 package.json
文件,並且內容簡單到姥姥家。
{ "ngPackage": {} }
最後,依然使用 ng build <libary name>
,會產生一個次級導入模塊。
至此,基本上利用 Angular Cli 能夠快速的構建一個可發佈於 Npm Angular 類庫,更復雜的能夠構建像 ngx-bootstrap、@angular/cdk/* 類庫。
Angular Cli 雖然提供很是便利的環境,可是對於一些複雜環境像 Delon 類庫(ng-alain基建系列類庫)包含着多個類庫、類庫又包含多個次級導入時,Angular Cli 會顯得有點囉嗦,特別是對每一個類庫的 angular.json 配置。其實 @angular-devkit/build-ng-packagr 很是簡單,若是將取進一步簡化,整個實現差很少至關於:
const path = require('path'); const ngPackage = require('ng-packagr'); const target = path.resolve(__dirname, './projects/<libary name>'); ngPackage .ngPackagr() .forProject(path.resolve(target, `ng-package.prod.json`)) .withTsConfig(path.resolve(target, 'tsconfig.lib.json')) .build() .then(() => { // 構建完成後乾點事 });
將上面的代碼放到 ./build.js
,執行:
node scripts/build.js
其結果完成是等價。
build()
返回的是一個 Promise
對象,意味着能夠確保構建開始前和結束後作一點額外的事。
ng-packagr 極大簡化 Angular 類庫被打包出一個 APF 規範建議,雖然它以 ng-
開頭,但本質上並不必定非要在 Angular 中運用,也可使用在 React、VUE。