esbuildからUpgradeModuleを起動する
背景
AngularJSというJavaScriptフレームワークがあります。最新バージョンは1.8です。
Long Term Supportが今年中に切れます[1]。
後継フレームワークにAngularがあります。
TypeScriptでの記述、コンポーネント指向の記述など、AngularJSとの相違点は名前が違う程度にはあります。移行パスとして、AngularからAngularJSのngモジュールを使う為の、UpgradeModuleが提供されています[2]。
しかし、PhoneCat Upgrade Tutorialに含まれる環境設定手順が不明瞭です。とくにSystemJSに関わる設定ファイルの全文が記載されておりません。環境設定でつまずくことが多いです。
そこで本文ではesbuildを使ってUpgradeModuleを起動する手順を記載します。
本文
AngularJSでの起動を確認
まず最初にAngularJSのまま起動できるか確認してみましょう。
git clone git@github.com:angular/angular-phonecat.git
cd angular-phonecat
npm start
ブラウザが http://localhost:8000 を開くと次のようなページが表示されます。
Angular 12のインストール
Zone.jsのコピー
AngularはZone.jsに依存しています。
ビルド時に結合せずにHTMLファイルから読み込みます。
HTMLファイルで読み込めるディレクトリにコピーを配置しておきます。
npm set-script copy-libs "cpx \"node_modules/{angular,angular-*,bootstrap/dist,jquery/dist,zone.js/bundles}/**/*\" app/lib -C"
Ivy形式への変換
If you are a library author, you should keep using the View Engine compiler as of version 9. [3]
AngularではAngular 9でコンパイラがViewEngineからIvyに変更されました。
後方互換性を考慮して、Angular用のライブラリはView Enigne向けに作り、使う人がngccコマンドを使って、Ivy形式に変換し、使います。
Angular 12もこのルールに従ってView Enigne向けのngモジュールを配布しています。
ngcc用の設定ファイルを追加
{
"compilerOptions": {
"experimentalDecorators": true
}
}
postinstallスクリプトでngccを実行
ライブラリーをnpm installしたときに一度だけngccでIvy形式に変更すればよいです。
postinstallスクリプトで変換します。
npm set-script postinstall "npm run copy-libs && ngcc --tsconfig tsconfig.json"
インストール
最新のAngularをインストールします。
執筆時点ではAngular 12がインストールされます。
npm install --save @angular/core @angular/platform-browser @angular/upgrade rxjs tslib typescript zone.js
Angularアプリケーションの追加
src
ディレクトリを作成し、その中にAngularアプリケーションを追加します。
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [
BrowserModule,
],
})
export class AppModule {
}
app.ts
import { platformBrowser } from '@angular/platform-browser';
import { AppModule } from './app/app.module';
platformBrowser().bootstrapModule(AppModule);
ビルド
ビルドツールのインストール
npm install -D @angular-devkit/schematics @angular/compiler-cli esbuild tslib typescript
設定ファイルの作成
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/app.ts"
],
"include": [
"src/**/*.d.ts"
]
}
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"module": "es2020",
"lib": [
"es2018",
"dom"
]
}
}
ビルドして生成するスクリプトをgitignoreに追加
echo app/app.js >> .gitignore
echo out-tsc >> .gitignore
ビルドスクリプトを追加
npm set-script build "ngc --project tsconfig.app.json && esbuild out-tsc/app/app.js --bundle --outfile=app/app.js"
npm set-script prestart "npm install && npm run build"
npm start
を実行すれば、ビルドが成功するはずです。
UpgradeModuleを使ってAngularJSアプリケーションを起動
@angular/upgradeをインストール
npm install -D @angular/upgrade
AngularアプリケーションからAngularJSアプリケーションを起動
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({
imports: [
BrowserModule,
UpgradeModule
],
})
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
ngDoBootstrap() {
this.upgrade.bootstrap(document.documentElement, ['phonecatApp']);
}
}
AngularJSの起動をやめる
app/index.html
からAngularJSを起動するためのキーワードng-app="phonecatApp"
を削除します。
zone.js
とapp.js
の読込を追加します。
DOMの読込完了後に実行するためにdefer
属性をつけることに気をつけて下さい。
defer
属性をつけないと、エラーは起きませんが、何も表示されません。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Google Phone Gallery</title>
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="app.animations.css" />
<script src="lib/jquery/dist/jquery.js"></script>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular-animate/angular-animate.js"></script>
<script src="lib/angular-resource/angular-resource.js"></script>
<script src="lib/angular-route/angular-route.js"></script>
<script src="app.module.js"></script>
<script src="app.config.js"></script>
<script src="app.animations.js"></script>
<script src="core/core.module.js"></script>
<script src="core/checkmark/checkmark.filter.js"></script>
<script src="core/phone/phone.module.js"></script>
<script src="core/phone/phone.service.js"></script>
<script src="phone-list/phone-list.module.js"></script>
<script src="phone-list/phone-list.component.js"></script>
<script src="phone-detail/phone-detail.module.js"></script>
<script src="phone-detail/phone-detail.component.js"></script>
<script defer src="lib/zone.js/bundles/zone.umd.js"></script>
<script defer src="app.js"></script>
</head>
<body>
<div class="view-container">
<div ng-view class="view-frame"></div>
</div>
</body>
</html>
npm start
を実行すれば、ハイブリッドアプリケーションの起動が成功します。
ブラウザで http://localhost:8000 を開くと、変更前と全く同じページが表示されます。
ここから先はPhoneCat Upgrade Tutorialの手順に従えば、AngularJSからAngularへのアップグレードを体験できます。
参考資料
Discussion