とんかつ時々あんどーなつ

〜たとえ低空でも飛行していられるように〜

Angular v12 へのアップデートとマイグレーション

Angular v12.0.0 が出てから 1 ヶ月くらい経つのでバージョンアップを実施した。

ステップ

ng update コマンドでアップデート可能なパッケージを確認

ng update コマンドでどのパッケージがアップデート可能か確認した。今回は angular/cli, angular/core, ngrx/store の 3 つが対象だった。

yarn ng update
yarn run v1.22.10
$ ng update
The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via yarn.
Installed packages for tooling via yarn.
Using package manager: 'yarn'
Collecting installed dependencies...
Found 37 dependencies.
    We analyzed your package.json, there are some packages to update:

      Name                               Version                  Command to update
     --------------------------------------------------------------------------------
      @angular/cli                       11.2.10 -> 12.0.3        ng update @angular/cli
      @angular/core                      11.2.11 -> 12.0.4        ng update @angular/core
      @ngrx/store                        11.1.1 -> 12.0.0         ng update @ngrx/store

    There might be additional packages which don't provide 'ng update' capabilities that are outdated.
    You can update the additional packages by running the update command of your package manager.
✨  Done in 10.44s.

angular/xxx をアップデート

Angularアップデートガイド の手順で angular/core と angular/cli をアップデートする。アップデートと一緒に必要なマイグレーションも自動で実行される。よい。

yarn ng update @angular/core@12 @angular/cli@12
yarn run v1.22.10
$ ng update @angular/core@12 @angular/cli@12
The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via yarn.
Installed packages for tooling via yarn.
Using package manager: 'yarn'
Collecting installed dependencies...
Found 37 dependencies.
Fetching dependency metadata from registry...
    Updating package.json with dependency @angular-devkit/build-angular @ "12.0.3" (was "0.1102.10")...
    Updating package.json with dependency @angular/cli @ "12.0.3" (was "11.2.10")...
    Updating package.json with dependency @angular/compiler-cli @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency karma @ "6.3.3" (was "5.2.3")...
    Updating package.json with dependency typescript @ "4.2.4" (was "4.0.5")...
    Updating package.json with dependency @angular/animations @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/common @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/compiler @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/core @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/forms @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/platform-browser @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/platform-browser-dynamic @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency @angular/router @ "12.0.4" (was "11.2.11")...
    Updating package.json with dependency zone.js @ "0.11.4" (was "0.10.3")...
  UPDATE package.json (1824 bytes)
✔ Packages successfully installed.
** Executing migrations of package '@angular/cli' **

❯ Remove deprecated options from 'angular.json' that are no longer present in v12.
  UPDATE angular.json (4719 bytes)
  Migration completed.

❯ Update 'zone.js' to version 0.11.x.
  Read more about this here: https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md#breaking-changes-since-zonejs-v0111
  UPDATE src/polyfills.ts (2814 bytes)
  UPDATE src/test.ts (750 bytes)
  UPDATE src/environments/environment.ts (666 bytes)
  Migration completed.

❯ Remove 'emitDecoratorMetadata' TypeScript compiler option.
  Decorator metadata is no longer needed by Angular.
  Read more about this here: https://www.typescriptlang.org/docs/handbook/decorators.html#metadata
    Skipping migration as the workspace uses third-party builders which may require "emitDecoratorMetadata" TypeScript compiler option.
  Migration completed.

❯ Lazy loading syntax migration.
  Update lazy loading string syntax to use dynamic imports.
  Migration completed.

❯ Remove deprecated ViewEngine-based i18n build and extract options.
  Options present in the configuration will be converted to use non-deprecated options.
  Migration completed.

❯ Updates Web Worker consumer usage to use the new syntax supported directly by Webpack 5.
  Migration completed.

❯ Remove invalid 'skipTests' option in '@schematics/angular:module' Angular schematic options.
  Migration completed.

** Executing migrations of package '@angular/core' **

❯ In Angular version 12, the type of ActivatedRouteSnapshot.fragment is nullable.
  This migration automatically adds non-null assertions to it.
  Migration completed.

❯ `XhrFactory` has been moved from `@angular/common/http` to `@angular/common`.
  Migration completed.

❯ Automatically migrates shadow-piercing selector from `/deep/` to the recommanded alternative `::ng-deep`.
  Migration completed.

✨  Done in 91.88s.

production builds by default

v12 から build configuration がデフォルトで production に変更される。そのための migration は手動のコマンドが用意されているので自分で migration コマンドを実行する。

yarn ng update @angular/cli@12 --migrate-only production-by-default
yarn run v1.22.10
$ ng update @angular/cli@12 --migrate-only production-by-default
Package specifier has no effect when using "migrate-only" option.
Using package manager: 'yarn'
Collecting installed dependencies...
Found 37 dependencies.
** Executing 'production-by-default' of package '@angular/cli' **

❯ Optional migration to update Angular CLI workspace configurations to 'production' mode by default.
    Cannot update "deploy" target configuration as it's using "angular-cli-ghpages:deploy"
    which is a third-party builder. This target configuration will require manual review.
  UPDATE angular.json (4973 bytes)
  Migration completed.

✨  Done in 1.05s.

builder options の見直し

production builds by default に合わせて builder options のデフォルト値が変更になっている。

https://github.com/angular/angular-cli/commit/656f8d75a3368a5affd1c55145841123dafdb007

そのため、angular.json を見直し更新していく。修正前の build architect は下記のような感じ。

"build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
    "outputPath": "dist/angular-architecture",
    "index": "src/index.html",
    "main": "src/main.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "tsconfig.app.json",
    "assets": [
      "src/favicon.ico",
      "src/assets"
    ],
    "styles": [
      "src/styles.scss"
    ],
    "scripts": [],
    "vendorChunk": true,
    "extractLicenses": false,
    "buildOptimizer": false,
    "sourceMap": true,
    "optimization": false,
    "namedChunks": true
  },
  "configurations": {
    "production": {
      "fileReplacements": [
        {
          "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.prod.ts"
        }
      ],
      "optimization": true,
      "outputHashing": "all",
      "sourceMap": false,
      "namedChunks": false,
      "extractLicenses": true,
      "vendorChunk": false,
      "buildOptimizer": true,
      "budgets": [
        {
          "type": "initial",
          "maximumWarning": "500kb",
          "maximumError": "6mb"
        },
        {
          "type": "anyComponentStyle",
          "maximumWarning": "2kb",
          "maximumError": "4kb"
        }
      ]
    },
    "development": {}
  },
"defaultConfiguration": "production"
},

デフォルトが development のときの名残(?)で optimization, buildOptimizer, sourceMap, extractLicenses, namedChunks, vendorChunk の設定が今のデフォルト値の反対になっている。production configuration では更にそれを反対に(今のデフォルト値に合うように)上書きをしていて冗長になっているので、ここを修正する。

diff --git a/angular.json b/angular.json
index 44183f6..d9f8a1d 100644
--- a/angular.json
+++ b/angular.json
@@ -36,13 +36,7 @@
             "styles": [
               "src/styles.scss"
             ],
-            "scripts": [],
-            "vendorChunk": true,
-            "extractLicenses": false,
-            "buildOptimizer": false,
-            "sourceMap": true,
-            "optimization": false,
-            "namedChunks": true
+            "scripts": []
           },
           "configurations": {
             "production": {
@@ -52,13 +46,7 @@
                   "with": "src/environments/environment.prod.ts"
                 }
               ],
-              "optimization": true,
               "outputHashing": "all",
-              "sourceMap": false,
-              "namedChunks": false,
-              "extractLicenses": true,
-              "vendorChunk": false,
-              "buildOptimizer": true,
               "budgets": [
                 {
                   "type": "initial",
@@ -72,7 +60,14 @@
                 }
               ]
             },
-            "development": {}
+            "development": {
+              "optimization": false,
+              "buildOptimizer": false,
+              "sourceMap": true,
+              "extractLicenses": false,
+              "namedChunks": true,
+              "vendorChunk": true
+            }
           },
           "defaultConfiguration": "production"
         },

非推奨になった --prod option の使用をやめる

production builds by default になったことによって build 時の --prod option が非推奨になった。

https://github.com/angular/angular-cli/pull/20128

CI などで production build のチェックをする際に --prod を使っているケースがあるので削除する。

感想

デフォルトの build options の変更で手作業がいつもより多い印象だが、それでもメジャーバージョンアップが楽になっていると感じた。

アップデートにおける差分は https://github.com/kasaharu/angular-architecture/pull/61 を見るとわかる。