iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 16
0
Modern Web

高效 Coding 術:Angular Schematics 實戰三十天系列 第 16

[高效 Coding 術:Angular Schematics 實戰三十天] Day15 - ng update?

筆者在 Day13 的時候有跟大家分享過 ng add 的原理與運作方式,而 ng update 雖然也是走同樣的路徑,只不過筆者覺得後者在後續處理上,跟其他的 Schematics 有滿大的不同。

究竟有多大的不同呢?

update.json

首先一樣先來看看 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 時,可以一併輸入的參數。

ng update 的參數

雖然參數很多,但實際使用時,需要特別留意以下規則:

alltrue 時無法指定更新特定的 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

migrateOnlytrue 時, 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 ,強制讓它從指定的版本開始更新。

最後,筆者使用這張流程圖結束這個回合:

Imgur

本日結語

筆者在研讀這篇文章的時候,真的是死了不少腦細胞。本來 Schematics 的相關文章就已經不多了,其中有特別提到 ng update 的更是少之又少,而且還都是三言兩語帶過而已,更不用提實作範例了。

所以如果內容有什麼不正確的地方,還請不吝批評指教,感激不盡!

明天筆者一樣會帶著大家實作一次 ng update 的練習,敬請期待!

參考資料


上一篇
[高效 Coding 術:Angular Schematics 實戰三十天] Day14 - 實戰 ng add
下一篇
[高效 Coding 術:Angular Schematics 實戰三十天] Day16 - 實戰 ng update
系列文
高效 Coding 術:Angular Schematics 實戰三十天32

尚未有邦友留言

立即登入留言