筆者在 Day13 的時候有跟大家分享過 ng add
的原理與運作方式,而 ng update
雖然也是走同樣的路徑,只不過筆者覺得後者在後續處理上,跟其他的 Schematics 有滿大的不同。
究竟有多大的不同呢?
首先一樣先來看看 ng update
的設定 - update.json
檔:
{
"$schema": "http://json-schema.org/schema",
"$id": "ng-cli://commands/update.json",
"description": "Updates your application and its dependencies. See https://update.angular.io/",
"$longDescription": "./update-long.md",
"$scope": "all",
"$aliases": [],
"$type": "schematics",
"$impl": "./update-impl#UpdateCommand",
"type": "object",
"allOf": [
{
"$ref": "./definitions.json#/definitions/base"
},
{
"type": "object",
"properties": {
"packages": {
"description": "The names of package(s) to update.",
"type": "array",
"items": {
"type": "string"
},
"$default": {
"$source": "argv"
}
},
"force": {
"description": "If false, will error out if installed packages are incompatible with the update.",
"default": false,
"type": "boolean"
},
"all": {
"description": "Whether to update all packages in package.json.",
"default": false,
"type": "boolean"
},
"next": {
"description": "Use the largest version, including beta and RCs.",
"default": false,
"type": "boolean"
},
"migrateOnly": {
"description": "Only perform a migration, does not update the installed version.",
"type": "boolean"
},
"from": {
"description": "Version from which to migrate from. Only available with a single package being updated, and only on migration only.",
"type": "string"
},
"to": {
"description": "Version up to which to apply migrations. Only available with a single package being updated, and only on migrations only. Requires from to be specified. Default to the installed version detected.",
"type": "string"
},
"allowDirty": {
"description": "Whether to allow updating when the repository contains modified or untracked files.",
"type": "boolean"
},
"verbose": {
"description": "Display additional details about internal operations during execution.",
"type": "boolean",
"default": false
},
"skipCommits": {
"description": "Do not create source control commits for updates and migrations.",
"type": "boolean",
"default": false,
"aliases": ["C"]
}
}
}
]
}
這一大串設定除了 $impl
之外,很明顯地在 allOf
裡多了很多屬性的設定,而這些屬性是指使用者在終端機中輸入 ng update
時,可以一併輸入的參數。
雖然參數很多,但實際使用時,需要特別留意以下規則:
當
all
為true
時無法指定更新特定的 Package ,migrateOnly
也不得為true
。
例如:
ng update @angular/material # ok
ng update --all=true # ok
ng update --all=true --migrateOnly=true # error
ng update @angular/material --all=true # error
migrateOnly
為true
時,from
為必填,且僅能指定一個 Package
例如:
ng update @angular/material --migrateOnly=true --from="1.0.0" # ok
ng update @angular/material --migrateOnly=true # error
ng update @angular/material @angular/cdk --migrateOnly=true --from="1.0.0" # error
from
&to
必須是 1~30個位數的數字。低標:
/^\d{1,30}(\.\d{1,30})*/
。
完整格式:/^\d{1,30}\.\d{1,30}\.\d{1,30}/
。
例如:
ng update @angular/material --migrateOnly=true --from="1" #ok
ng update @angular/material --migrateOnly=true --from="1.0" #ok
ng update @angular/material --migrateOnly=true --from="1.0.0" #ok
ng update @angular/material --migrateOnly=true --from="v1.0.0" #error
除上述參數規則之外,另外還需要特別留意的是,因為 ng update
會檢查當前 Git 的狀態,如果當前有變更尚未 Commit 的話,也會無法使用。除非加上 --allowDirty=true
,才會忽略這個檢查。
另一個比較特別的地方是, ng update
做完的時候,會自動 commit
一筆變更。所以如果你希望它不要幫你做的話,可以加上 --skipCommits=true
,它就不會幫你 commit
了。
筆者覺得 ng update
是 Schematics 中最複雜的一個指令,閱讀 update-impl.ts
的時候讓筆者的腦細胞死了大半。
它跟其它的 Schematics 最不一樣的是,當我們在使用 ng update
指令的時候,它解析的不是原本在 package.json
裡的 schematics
設定,而是要另外再設一組專門給 ng update
使用的 ng-update
設定。
如:
{
"//": "略",
"ng-update": {
"migrations": "./src/migration.json"
}
}
而大家應該也會發現在上述的設定,有另一個 JSON 檔的出現。這個 JSON 檔的內容大概像是這樣:
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"migration-01": {
"version": "1.0.0",
"description": "Updates to 1.0.0",
"factory": "./ng-update/index#updateToV1"
},
"migration-02": {
"version": "2.0.0",
"description": "Updates to 2.0.0",
"factory": "./ng-update/index#updateToV2"
}
}
}
乍看之下是跟 collection.json
很像,但多了 version
的設定。這是為了因應如果多個版本之間有破壞性變更時, ng update
會很聰明的從最近的變動開始處理。
用上述設定來舉例說明:
1.x.x
,當我們輸入 ng update
時,會使用 migration-02
的設定。0.x.x
,當我們輸入 ng update
時,會先使用 migration-01
的設定,再使用 migration-02
的設定。是不是很聰明?!
當然,使用者也可以用上個小節提到的參數 -
from
,強制讓它從指定的版本開始更新。
最後,筆者使用這張流程圖結束這個回合:
筆者在研讀這篇文章的時候,真的是死了不少腦細胞。本來 Schematics 的相關文章就已經不多了,其中有特別提到 ng update
的更是少之又少,而且還都是三言兩語帶過而已,更不用提實作範例了。
所以如果內容有什麼不正確的地方,還請不吝批評指教,感激不盡!
明天筆者一樣會帶著大家實作一次 ng update
的練習,敬請期待!