隨著自己開發的 Angular 專案越來越多,有時候難免會覺得自己好像一直在做重複的事,因此我們會開始試著將可以重複使用的模組拆成獨立的函式庫,就像是保哥的認識 Angular Library 函式庫專案並學會自製 Angular 表單驗證器模組文章裡所分享的這樣。
關於如何在建立函式庫專案或如何在自己專案內新增函式庫,保哥的文章內介紹的非常清楚,筆者就不再贅述。有興趣的邦友們一定要仔細研讀!
同樣的,我們也能夠將把 Schematics 像函式庫一樣整合到我們的 Angular 專案裡,讓別人可以直接透過 ng add
將你的 Package 加到他們的專案內、可以直接使用 ng generate
來產生程式碼、可以直接使用 ng update
來調整因為破壞性變更所以需要的程式碼,
就像是 Angular Components 一樣。
所以今天筆者要來分享,如何將自己的 Schematics 整合進 Angular 專案裡。
首先我們需要一個 Angular 專案,沒有現成的專案的話可以直接新建一個:
ng new schematics-day18
接著輸入以下指令以在專案裡新增函式庫:
ng g library my-library
等 CLI 跑完之後你會發現,怎麼多了一堆檔案也改了好幾個檔案:
別擔心,這些都是 Angular CLI 內建的 Schematics 幫我們做的設定,至此我們就算是新增了一個函式庫在我們的專案內,接下來則是要把我們之前做好的的 schematcis 整合進去。
接著在剛剛建立的函式庫的根目錄底下新增一個名為 schematics
的資料夾,並把我們之前寫的Schematics 像這樣複製一份過去:
搬過去之後可能會發現有很多檔案是不需要追蹤,因為那些檔案其實只要編譯過就會自動產生,這時我們可以在 .gitignore
裡新增要忽略追蹤的檔案,像這樣:
# for Schematics
*/**/schematics/**/*.js
*/**/schematics/**/*.js.map
*/**/schematics/**/*.d.ts
!*/**/schematics/**/schema.d.ts
接著把 Schematics 的路徑設定加進 my-library
裡的 package.json
裡:
{
"//": "略",
"schematics": "./schematics/collection.json",
"ng-update": {
"migrations": "./schematics/migration.json"
}
}
為了將 Schematics 跟 Library 整合在一起,我們必須將 Library 跟 Schematics 分開編譯,所以我們需要在 my-library
的根目錄裡新增一個 tsconfig.schematics.json
,內容如下:
{
"compilerOptions": {
"baseUrl": ".",
"lib": [
"es2018",
"dom"
],
"declaration": true,
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitThis": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"rootDir": "schematics",
"outDir": "../../dist/my-lib/schematics",
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es6",
"types": [
"jasmine",
"node"
]
},
"include": [
"schematics/**/*"
],
"exclude": [
"schematics/*/files/**/*"
]
}
其中較需要注意的設定是:
rootDir
- 需要編譯的 Schematics 目錄路徑位置 。outDir
- 要將編譯完的檔案輸出到什麼位置。然後將以下 scripts
的設定加進 my-library
的 package.json
裡:
{
"//": "略",
"scripts": {
"build": "../../node_modules/.bin/tsc -p tsconfig.schematics.json",
"copy:schemas": "cp --parents schematics/*/schema.json ../../dist/my-lib/",
"copy:files": "cp --parents -p schematics/*/files/** ../../dist/my-lib/",
"copy:collection": "cp schematics/collection.json ../../dist/my-lib/schematics/collection.json",
"copy:migration": "cp schematics/migration.json ../../dist/my-library/schematics/migration.json",
"postbuild": "npm run copy:schemas && npm run copy:files && npm run copy:collection"
}
}
這些設定的目的是為了:
build
- 使用 tsconfig.schematics.json
的設定來編譯我們的 Schematics 。copy:*
- 將編譯過後的檔案複製到正確的路徑。postbuild
- 一次做完 copy:schemas
、 copy:files
、 copy:collection
、 copy:migration
這四個動作。如此一來,我們就完成了所有配置,接下來就可以將它編譯出來玩了!
cp --parents
是 Windows 或 Linus 的作業系統建議採用的指令與參數,當然各位也可以用任何自己所熟悉的指令將其替換,只要能夠達到同樣的目的即可。而特別注意的是,當你是使用 macOS 實作此練習時,如果使用上述指令來操作很有可能會遇到以下錯誤:
這時我們只要將原本使用
cp --parents
的部份改為使用rsync -R
來代替即可。如:
{ "copy:schemas": "rsync -R schematics/*/schema.json ../../dist/my-library/", "copy:files": "rsync -R schematics/*/files/** ../../dist/my-library/" }
剛剛在配置的時候有說過,我們必須將 Library 跟 Schematics 分開編譯,所以先在終端機輸入以下指令編譯我們的 Library :
ng build my-library
結果:
接著輸入以下指令前往 my-library
的根目錄:
cd projects/my-library
再輸入以下指令編譯我們的 Schematics :
npm run build
結果:
當 Library 跟 Schematics 都編譯好之後,如果要在該專案中直接使用它的話,就需要輸入以下指令將它跟專案連結起來:
npm link dist/my-library
注意!輸入此指令時,當前路徑要在專案根目錄之中。
結果:
連結完成之後,就可以輸入以下指令來產生程式碼了:
ng generate my-library:hello-world feautre/leo-chen
結果:
今天的程式碼:https://github.com/leochen0818/angular-schematics-for-it-help-day18 。
筆者覺得本篇的含金量其實頗高,因為除了官方的教學文件外,就沒有其他文章在分享關於這部份的設定。雖然可以說是官方文件寫得很好,但從另一個角度來看,一旦官方文件有錯,就會讓正在學習的人不知道該怎麼處理才好。
就像筆者雖然此篇也是靠著官方文件與保哥文章交互參照著練習與驗證,但很少人知道 cp --parents
其實藏了一個這麼大的雷,而且官方提供給大家下載的範例也有問題,根本就 build 不起來。
如果筆者今天不是為了要寫鐵人賽,又或是沒有這麼強烈的學習動機,可能會就這樣算了,甚至還會降低對官方文件的信任度。
總而言之,希望大家透過今天的練習,都能成功將 Schematics 與 Angular 專案整合在一起!
接下來筆者將會介紹幾個好用的工具,敬請期待!