はじめに
Angular12で作成されたWEBサイトを最新(Angular17)にアップデートする機会があったので、ソースと手順を残しておく。
Nxを使ったモノレポ構成だったこともあり、簡単にはいかなかった。
以下のAngular12のソースを17にバージョンアップする。
Angular + Nest Example2
Angular CLI: 12.2.11
Node: 16.12.0
Package Manager: npm 8.1.0
npm-check-updatesを使用した更新(失敗)
まずはnpm-check-updatesを試してみる。
ncu -u
でpackage.jsonをまとめて最新にする。
PS C:\Work\git\angular-nest-example2> ncu -u
Upgrading C:\Work\git\angular-nest-example2\package.json
[====================] 62/62 100%
@angular-devkit/build-angular ~12.2.0 → ~17.0.7
@angular-eslint/eslint-plugin ~12.3.0 → ~17.1.1
@angular-eslint/eslint-plugin-template ~12.3.0 → ~17.1.1
・
・中略
・
typescript ~4.3.5 → ~5.3.3
zone.js ~0.11.4 → ~0.14.2
Run npm install to install new versions.
・・・何となく無理っぽい気はするけど、まあダメもとでやってみるか。
npm install
だと依存関係エラーが出たので、とりあえずnpm install --legacy-peer-deps
で強引に進め、インストールは成功。
だが、実行時に、以下のエラーが発生。
Nxの構成が大きく変わっているらしく、そのあたりをなんとかする必要がありそう。
Nxコマンドを使用した更新(失敗)
Nxのコマンドにも自動更新があるので、今度はこちらを試してみる。
Automate Updating Dependencies | Nx
まずはnx migrate latest
コマンドでモジュールのバージョンを更新。これは成功した。
またnpm install --legacy-peer-deps
で強引にモジュールをインストールする。
次にnx migrate --run-migrations
を実行したが、失敗。
> NX Failed to run block-template-entities from @angular/core. This workspace is NOT up to date!
> NX import_typescript3.default.getDecorators is not a function
ネットの情報をもとにnx.json
やproject.json
などを変更してみたが、どうにも解決できず・・・。
諦めて、Nxのプロジェクトを1から作り直すことにする。
新規Nxプロジェクトの再作成
まずはnestの環境(api)を生成。
npx create-nx-workspace@latest --preset nest --name angular-nest-example3 --appName api --nxCloud true
作成されたプロジェクトフォルダに移動して、angularの環境(web)を生成。
npm install @nrwl/angular
nx generate @nrwl/angular:application --name web
とりあえずこれで「api」と「web」のフォルダが作成され、nx serve api、nx serve webでそれぞれ起動できる。
ソースコピー
変更元のソースを新環境にコピーする。
apps\api\src
、apps\api\src
の配下は丸ごと上書きでいいはず。
package.json
は、scripts部分は上書き。
dependenciesなどは、この後コマンドでモジュール追加していく。
その他、tsconfig.json
などは、差分を見比べて必要な部分をマージしていく。
モジュールの追加
変更元のpackage.json
を参考に、必要なモジュールを追加していく。
npm install @angular/cdk --legacy-peer-deps
npm install @angular/material --legacy-peer-deps
・
・
・
以下略
エラーの回避
npm start
で起動しようとすると、大量のエラーが出てきた・・・一つずつ回避していく。
relativeLinkResolution
relativeLinkResolution
の定義は、Angular15あたりで不要になったらしい。
Error: apps/web/src/app/app-routing.module.ts:19:46 - error TS2345: Argument of type '{ relativeLinkResolution: string; }' is not assignable to parameter of type 'ExtraOptions'.
Object literal may only specify known properties, and 'relativeLinkResolution' does not exist in type 'ExtraOptions'.
19 imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
↓ 単純に削除すればOK。
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
↓
imports: [RouterModule.forRoot(routes)],
entryComponents
entryComponents
の定義もAngular15あたりで不要になったらしい。
Error: apps/web/src/app/app.module.ts:113:5 - error TS2345: Argument of type '{ declarations: (typeof AppComponent | typeof SimpleDialogComponent | typeof TableDialogComponent | typeof ProgressSpinnerComponent)[]; imports: (typeof BrowserModule | ... 1 more ... | ModuleWithProviders<...>)[]; providers: (typeof HttpRequestInterceptor | ... 1 more ... | { ...; })[]; bootstrap: (typeof AppCompon...' is not assignable to parameter of type 'NgModule'.
Object literal may only specify known properties, and 'entryComponents' does not exist in type 'NgModule'.
113 entryComponents: [
~~~~~~~~~~~~~~~
↓ これも単純に削除すればOK。
@NgModule({
declarations: [
AppComponent,
SimpleDialogComponent,
TableDialogComponent,
ProgressSpinnerComponent,
],
imports: [
BrowserModule,
・
・ 中略
・
bootstrap: [AppComponent],
// entryComponents: [ ★←削除。
// SimpleDialogComponent,
// TableDialogComponent,
// ],
})
export class AppModule {}
Theming機能
Theming機能については、Angular15で大幅に仕様が変わったらしい。
インポートの時点でエラーが出ている。
./apps/web/src/assets/styles/styles.scss?ngGlobalStyle - Error: Module build failed (from ./node_modules/@angular-devkit/build-angular/node_modules/mini-css-extract-plugin/dist/loader.js):
HookWebpackError: Module build failed (from ./node_modules/@angular-devkit/build-angular/node_modules/sass-loader/dist/cjs.js):
Can't find stylesheet to import.
╷
4 │ @import '~@angular/material/theming';
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
それぞれ、以下のように変更する。
@import '~@angular/material/theming';
@include mat-core();
↓↓↓
@use 'node_modules/@angular/material' as mat;
@include mat.core();
以下、darkテーマを変更したときの修正例。
メソッド名などが微妙に変わっているが、変更後のメソッドに書き直すだけでだいたいいけた。
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent: mat-palette($mat-amber, A200, A100, A400);
$dark-warn: mat-palette($mat-deep-orange);
↓↓↓
$dark-primary: mat.define-palette(mat.$blue-grey-palette);
$dark-accent: mat.define-palette(mat.$amber-palette, A200, A100, A400);
$dark-warn: mat.define-palette(mat.$deep-orange-palette);
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);
↓↓↓
$dark-theme: mat.define-dark-theme((
color: (
primary: $dark-primary,
accent: $dark-accent,
warn: $dark-warn,
)
));
.dark-theme {
@include angular-material-theme($dark-theme);
}
↓↓↓
.dark-theme {
@include mat.all-component-themes($dark-theme);
}
.dark-theme-color {
background-color : mat-color($dark-background-palette, background)!important;
color: mat-color($dark-foreground-palette, text)!important;
}
↓↓↓
.dark-theme-color {
background-color : mat.get-color-from-palette(mat.$dark-theme-background-palette, background)!important;
color: mat.get-color-from-palette(mat.$dark-theme-foreground-palette, text)!important;
}
mat.$blue-grey-palette
などは、デフォルトで定義されているパレット。
定義の名称などは、以下に記載されている。
node_modules@angular\material\core\theming_palette.scss
定義済みのパレットの色などは、以下で確認できる。
https://m1.material.io/style/color.html#color-color-palette
その他
細かいデザインの修正
微妙にデザインが崩れているところがあるので、修正していく。
特に、Angular MaterialがMDC(Material Design Component)ベースに変更されたらしく、その影響で微妙なずれが発生している個所が多かった。
これも自動で更新するコマンドがあるようだが(参考「Migrating to MDC-based Angular Material Components」)、未確認。
一つ一つ個別に修正していく。
依存関係エラー対応
npm install
で発生していた依存関係エラーを確認する。
どうやらangular-resize-event
というモジュールが最新では使えなくなっているらしい。
新しいバージョンも出ておらず、変わるライブラリも見当たらなかったので、ResizeObserver
を使用する方法に書き直した。
これで--legacy-peer-deps
しなくてもモジュールインストールできるようになった。
完成
これで、一通り元と同じ状態になったはず。
変更後のソースは以下の通り。
変更履歴つき。
Angular + Nest Example3
Angular CLI: 17.0.6
Node: 20.9.0
Package Manager: npm 10.1.0
結局は最初から作り直したほうが早いかも、というお話でした。
(特に一気に複数バージョンアップする場合は。)