アプリのIonicバージョンを2から3に上げた。
- 特に参考にしたサイト
- アップグレードの大まかな流れ
- バージョン情報
- package.jsonを更新する
- ブラウザで動作確認(1回目):エラー
- ブラウザで動作確認(2回目):エラー
- ブラウザで動作確認(3回目):エラー
- ブラウザで動作確認(4回目):エラー
- ブラウザで動作確認(5回目):エラー
- ブラウザで動作確認(6回目):エラー
- ブラウザで動作確認(7回目):エラー
- ブラウザで動作確認(8回目):エラー
特に参考にしたサイト
このサイトが特に参考になった。この記事のStep1とStep2と同じことを本記事でもやっている(Step3は飛ばした気がする…)。ただ、本記事では、トライアンドエラー方式でこのアップグレード作業を進めたので、参考記事とは作業の順番と内容が多少違っている。
他にも、Angularのアップグレード前のバージョンと、後のバージョンを入力すると、更新作業のガイドを出してくれる便利なサイトもあったので、紹介しておく。
アップグレードの大まかな流れ
実装により違いは出るだろうが、Ionic 2 -> Ionic 3 へのアップグレード作業では、だいたい下記の手順が必要になる。ただ、前節でも述べたように、本記事では、修正→動作確認→エラー→修正 のトライアンドエラー方式で作業を進めたため、順不同であり、通常発生しないエラーも出ていると思われる。
package.jsonの更新
app.module.tsにBrowserModuleを追加する
httpを使っている場合は、HttpClientModuleに切り替える
index.htmlに
<script src="build/vendor.js"></script>
を追加する
バージョン情報
PC周りの環境
- Node : v8.1.4
- npm : 5.0.3
- OS : macOS High Sierra
アプリのバージョン - アップグレード前
- Ionic Framework : ionic-angular 2.0.0-rc.4
- Angular: 2.2.1
- @ionic/app-scripts : 1.1.4
- @ionic/cli-utils : 1.19.2
- ionic (Ionic CLI) : 3.20.0
アプリのバージョン - アップグレード後
- Ionic Framework : ionic-angular 3.9.2
- Angular: 5.2.9
- @ionic/app-scripts : 3.1.8
- @ionic/cli-utils : 1.19.2
- ionic (Ionic CLI) : 3.20.0
package.jsonを更新する
まず、npm-check-updatesを使って、更新可能なライブラリのバージョンを全てあげていく。
npm-check-updatesを使う前に、Ionic CLIのionic info
コマンドでアプリにおける現在のIonicのバージョンを確認する。
$ ionic info cli packages: (/usr/local/lib/node_modules) @ionic/cli-utils : 1.19.2 ionic (Ionic CLI) : 3.20.0 local packages: @ionic/app-scripts : 1.1.4 Ionic Framework : ionic-angular 2.0.0-rc.4 System: Node : v8.1.4 npm : 5.0.3 OS : macOS High Sierra Misc: backend : legacy
まだ何もしていないので、Ionicのバージョンは2のままである。
続いて、ncu
コマンドを実行して、アップグレード可能なライブラリをチェックする。なお、npm-check-updateをインストールしていない場合は、npm i -g npm-check-update
コマンドでインストールできる。
$ ncu Using package.json ⸨░░░░░░░░░░░░░░░░░░⸩ ⠙ : @angular/common 2.2.1 → 5.2.9 @angular/compiler 2.2.1 → 5.2.9 @angular/compiler-cli 2.2.1 → 5.2.9 @angular/core 2.2.1 → 5.2.9 @angular/forms 2.2.1 → 5.2.9 @angular/http 2.2.1 → 5.2.9 @angular/platform-browser 2.2.1 → 5.2.9 @angular/platform-browser-dynamic 2.2.1 → 5.2.9 @angular/platform-server 2.2.1 → 5.2.9 @ionic-native/core ^3.12.1 → ^4.6.0 @ionic-native/in-app-browser ^3.12.1 → ^4.6.0 @ionic/storage 1.1.7 → 2.1.3 cordova-ios 4.4.0 → 4.5.4 cordova-plugin-device ^1.1.6 → ^2.0.1 cordova-plugin-geolocation ^2.4.3 → ^4.0.1 cordova-plugin-inappbrowser ^1.7.1 → ^2.0.2 cordova-plugin-splashscreen ^4.0.3 → ^5.0.2 ionic-angular 2.0.0-rc.4 → 3.9.2 ionic-native 2.2.11 → 2.9.0 zone.js 0.6.26 → 0.8.24 @ionic/app-scripts 1.1.4 → 3.1.8 typescript 2.0.9 → 2.8.1 The following dependencies are satisfied by their declared version range, but the installed versionsare behind. You can install the latest versions without modifying your package file by using npm update. If you want to update the dependencies in your package file anyway, run ncu -a. cordova-plugin-statusbar ^2.2.3 → ^2.4.1 cordova-plugin-whitelist ^1.3.2 → ^1.3.3 cordova-sqlite-storage ^2.0.4 → ^2.3.0 rxjs ^5.0.1 → ^5.5.8 Run ncu with -u to upgrade package.json
更新可能なライブラリのバージョンは全てあげたいので、ncu -u
コマンドを実行する。これで、package.jsonが実際に更新される。
$ ncu -u ⸨░░░░░░░░░░░░░░░░░░⸩ ⠧ : @angular/common 2.2.1 → 5.2.9 @angular/compiler 2.2.1 → 5.2.9 @angular/compiler-cli 2.2.1 → 5.2.9 @angular/core 2.2.1 → 5.2.9 @angular/forms 2.2.1 → 5.2.9 @angular/http 2.2.1 → 5.2.9 @angular/platform-browser 2.2.1 → 5.2.9 @angular/platform-browser-dynamic 2.2.1 → 5.2.9 @angular/platform-server 2.2.1 → 5.2.9 @ionic-native/core ^3.12.1 → ^4.6.0 @ionic-native/in-app-browser ^3.12.1 → ^4.6.0 @ionic/storage 1.1.7 → 2.1.3 cordova-ios 4.4.0 → 4.5.4 cordova-plugin-device ^1.1.6 → ^2.0.1 cordova-plugin-geolocation ^2.4.3 → ^4.0.1 cordova-plugin-inappbrowser ^1.7.1 → ^2.0.2 cordova-plugin-splashscreen ^4.0.3 → ^5.0.2 ionic-angular 2.0.0-rc.4 → 3.9.2 ionic-native 2.2.11 → 2.9.0 zone.js 0.6.26 → 0.8.24 @ionic/app-scripts 1.1.4 → 3.1.8 typescript 2.0.9 → 2.8.1 cordova-plugin-statusbar ^2.2.3 → ^2.4.1 cordova-plugin-whitelist ^1.3.2 → ^1.3.3 cordova-sqlite-storage ^2.0.4 → ^2.3.0 rxjs ^5.0.1 → ^5.5.8
この時点では、まだpackage.jsonしか更新されていないので、npm update
コマンドで最新バージョンのライブラリをインストールする。
$ npm update npm WARN tsickle@0.27.2 requires a peer of typescript@>=2.4.2 <2.8 but none was installed. npm WARN @angular/platform-server@5.2.9 requires a peer of @angular/animations@5.2.9 but none was installed. npm WARN @ionic/app-scripts@1.1.4 requires a peer of @angular/tsc-wrapped@* but none was installed. npm WARN @ionic/app-scripts@1.1.4 requires a peer of sw-toolbox@* but none was installed. + @angular/compiler-cli@5.2.9 + @angular/core@5.2.9 + @angular/common@5.2.9 + cordova-ios@4.5.4 + cordova-plugin-device@2.0.1 + cordova-plugin-geolocation@4.0.1 + cordova-plugin-inappbrowser@2.0.2 + cordova-plugin-splashscreen@5.0.2 + ionic-angular@3.9.2 + ionic-native@2.9.0 + @ionic-native/in-app-browser@4.6.0 + zone.js@0.8.24 + cordova-plugin-statusbar@2.4.1 + @angular/forms@5.2.9 + rxjs@5.5.8 + @angular/compiler@5.2.9 + @angular/platform-browser-dynamic@5.2.9 + @angular/http@5.2.9 + @ionic/storage@2.1.3 + cordova-plugin-whitelist@1.3.3 + cordova-sqlite-storage@2.3.0 + @ionic-native/core@4.6.0 + @angular/platform-server@5.2.9 + @angular/platform-browser@5.2.9 added 16 packages, removed 19 packages and updated 68 packages in 15.598s
npm update
コマンド後に、ionic info
でアプリのIonicバージョンを確認すると、ionic-angular 2.0.0-rc.4
からionic-angular 3.9.2
に上がっていることがわかる。
$ ionic info cli packages: (/usr/local/lib/node_modules) @ionic/cli-utils : 1.19.2 ionic (Ionic CLI) : 3.20.0 local packages: @ionic/app-scripts : 1.1.4 Ionic Framework : ionic-angular 3.9.2 System: Node : v8.1.4 npm : 5.0.3 OS : macOS High Sierra Misc: backend : legacy
ブラウザで動作確認(1回目):エラー
この段階で一度ブラウザで動作確認をしてみた。Error: Cannot find module '@angular/tsc-wrapped/src/tsc'
が発生して、失敗した。
$ ionic serve Error: Cannot find module '@angular/tsc-wrapped/src/tsc' at Function.Module._resolveFilename (module.js:485:15) at Function.Module._load (module.js:437:25) at Module.require (module.js:513:17) at require (internal/module.js:11:18) at Object.<anonymous> (/node_modules/@ionic/app-scripts/dist/aot/aot-compiler.js:6:13) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:503:32) at tryModuleLoad (module.js:466:12) at Function.Module._load (module.js:458:3)
エラーError: Cannot find module '@angular/tsc-wrapped/src/tsc'
を回避するために、npm install @angular/tsc-wrapped --save
を実施した。
$ npm install @angular/tsc-wrapped --save npm WARN tsickle@0.27.2 requires a peer of typescript@>=2.4.2 <2.8 but none was installed. npm WARN @angular/platform-server@5.2.9 requires a peer of @angular/animations@5.2.9 but none was installed. npm WARN @ionic/app-scripts@1.1.4 requires a peer of sw-toolbox@* but none was installed. + @angular/tsc-wrapped@4.4.6 added 5 packages in 4.94s
ブラウザで動作確認(2回目):エラー
再度、ionic serve
コマンドでブラウザデバックを実施、別のエラーTypeError: ts.createNodeArray is not a function
が発生した。
$ ionic serve TypeError: ts.createNodeArray is not a function at Object.<anonymous> (node_modules/@angular/compiler-cli/src/metadata/evaluator.js:661:16) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:503:32) at tryModuleLoad (module.js:466:12) at Function.Module._load (module.js:458:3) at Module.require (module.js:513:17) at require (internal/module.js:11:18) at Object.<anonymous> (/node_modules/@angular/compiler-cli/src/metadata/collector.js:19:19) at Module._compile (module.js:569:30)
npm update
コマンドを実施した時に、npm WARN tsickle@0.27.2 requires a peer of typescript@>=2.4.2 <2.8 but none was installed.
と怒られていたのを思い出したので、typescriptのバージョンを下げる。
$ npm i --save typescript@2.6.2 npm WARN @angular/platform-server@5.2.9 requires a peer of @angular/animations@5.2.9 but none was installed. npm WARN @ionic/app-scripts@1.1.4 requires a peer of sw-toolbox@* but none was installed. + typescript@2.6.2 updated 1 package in 2.9s
ブラウザで動作確認(3回目):エラー
三度、ブラウザデバックを実施、2件のエラーが発生した。
エラー: 1
Class 'Subject<T>' incorrectly extends base class 'Observable<T>'. Types of property 'lift' are incompatible. Type '<R>(operator: Operator<T, R>) => Observable<T>' is not assignable totype '<R>(operator: Operator<T, R>) => Observable<R>'. Type 'Observable<T>' is not assignable to type 'Observable<R>'. Type 'T' is not assignable to type 'R'.
エラー: 2
Class 'WebSocketSubject<T>' incorrectly extends base class 'AnonymousSubject<T>'. Types of property 'lift' are incompatible. Type '<R>(operator: Operator<T, R>) => WebSocketSubject<R>' is not assignable to type '<R>(operator: Operator<T, R>) => Observable<T>'. Type 'WebSocketSubject<R>' is not assignable to type 'Observable<T>'. Types of property 'operator' are incompatible. Type 'Operator<any, R>' is not assignable to type 'Operator<any, T>'. Type 'R' is not assignable to type 'T'.
$ ionic serve Starting app-scripts server: --address 0.0.0.0 --port 8100 --livereload-port 35729 --dev-logger-port 53703 --nobrowser - Ctrl+C to cancel [13:46:00] watch started ... [13:46:00] build dev started ... [13:46:00] clean started ... [13:46:00] clean finished in 2 ms [13:46:00] copy started ... [13:46:00] transpile started ... [13:46:04] typescript: node_modules/ionic-native/node_modules/rxjs/Subject.d.ts, line: 16 Class 'Subject<T>' incorrectly extends base class 'Observable<T>'. Types of property 'lift' are incompatible. Type '<R>(operator: Operator<T, R>) => Observable<T>' is not assignable totype '<R>(operator: Operator<T, R>) => Observable<R>'. Type 'Observable<T>' is not assignable to type 'Observable<R>'. Type 'T' is not assignable to type 'R'. L16: export declare class Subject<T> extends Observable<T> implements ISubscription { L17: observers: Observer<T>[]; [13:46:04] typescript: node_modules/ionic-native/node_modules/rxjs/observable/dom/WebSocketSubject.d.ts, line: 23 Class 'WebSocketSubject<T>' incorrectly extends base class 'AnonymousSubject<T>'. Types of property 'lift' are incompatible. Type '<R>(operator: Operator<T, R>) => WebSocketSubject<R>' is not assignable to type '<R>(operator: Operator<T, R>) => Observable<T>'. Type 'WebSocketSubject<R>' is not assignable to type 'Observable<T>'. Types of property 'operator' are incompatible. Type 'Operator<any, R>' is not assignable to type 'Operator<any, T>'. Type 'R' is not assignable to type 'T'. L23: export declare class WebSocketSubject<T> extends AnonymousSubject<T> { L24: url: string; [13:46:04] transpile failed [13:46:04] dev server running: http://localhost:8100/ [OK] Development server running! Local: http://localhost:8100 External: http://10.4.71.18:8100 DevApp: TSCGuide@8100 on MacBook-Pro.local [13:46:04] copy finished in 4.32 s [13:46:04] watch ready in 4.35 s
このサイトを参考に、tsconfing.jsonに"compilerOptions":{"skipLibCheck": true}
を追加することによって、エラーを回避した。
"compilerOptions":{ "skipLibCheck": true }
ブラウザで動作確認(4回目):エラー
4度目のブラウザでの動作確認を実施
$ ionic serve Starting app-scripts server: --address 0.0.0.0 --port 8100 --livereload-port 35729 --dev-logger-port 53703 --nobrowser - Ctrl+C to cancel [14:04:00] watch started ... [14:04:00] build dev started ... [14:04:00] clean started ... [14:04:00] clean finished in 1 ms [14:04:00] copy started ... [14:04:00] transpile started ... [14:04:02] transpile finished in 2.33 s [14:04:02] preprocess started ... [14:04:02] preprocess finished in less than 1 ms [14:04:02] webpack started ... [14:04:02] copy finished in 2.46 s [14:04:09] webpack finished in 6.65 s [14:04:09] sass started ... [14:04:10] sass finished in 1.25 s [14:04:10] postprocess started ... [14:04:10] postprocess finished in less than 1 ms [14:04:10] lint started ... [14:04:10] build dev finished in 10.26 s [14:04:10] watch ready in 10.30 s [14:04:10] dev server running: http://localhost:8100/ [OK] Development server running! [14:04:12] lint finished in 2.51 s
ランタイムエラーCannot find module "localforage"
が発生した。
Runtime Error Cannot find module "localforage" Stack Error: Cannot find module "localforage" at Object.<anonymous> (http://localhost:8100/build/main.js:152241:7) at __webpack_require__ (http://localhost:8100/build/main.js:20:30) at Object.<anonymous> (http://localhost:8100/build/main.js:44047:67) at __webpack_require__ (http://localhost:8100/build/main.js:20:30) at Object.<anonymous> (http://localhost:8100/build/main.js:37686:73) at __webpack_require__ (http://localhost:8100/build/main.js:20:30) at Object.<anonymous> (http://localhost:8100/build/main.js:151732:80) at __webpack_require__ (http://localhost:8100/build/main.js:20:30) at Object.<anonymous> (http://localhost:8100/build/main.js:113027:73) at __webpack_require__ (http://localhost:8100/build/main.js:20:30)
このサイトを参考に、ライブラリionic-storage
のアンインストールとインストールを実施することによって、エラーを回避した。
npm uninstall --save @ionic/storage npm install --save @ionic/storage
ブラウザで動作確認(5回目):エラー
ブラウザで動作確認、エラーCan't resolve all parameters for Storage: (?).
が発生した。ionic-storage
のバージョンが上がり、使い方が変わったことが原因となる。
Runtime Error Can't resolve all parameters for Storage: (?). Stack Error: Can't resolve all parameters for Storage: (?). at syntaxError (http://localhost:8100/build/main.js:113815:34) at CompileMetadataResolver._getDependenciesMetadata (http://localhost:8100/build/main.js:129030:35) at CompileMetadataResolver._getTypeMetadata (http://localhost:8100/build/main.js:128865:26) at CompileMetadataResolver._getInjectableMetadata (http://localhost:8100/build/main.js:128845:21) at CompileMetadataResolver.getProviderMetadata (http://localhost:8100/build/main.js:129205:40) at http://localhost:8100/build/main.js:129116:49 at Array.forEach (<anonymous>) at CompileMetadataResolver._getProvidersMetadata (http://localhost:8100/build/main.js:129076:19) at CompileMetadataResolver.getNgModuleMetadata (http://localhost:8100/build/main.js:128644:50) at JitCompiler._loadModules (http://localhost:8100/build/main.js:147735:87)
このサイトの「Update Steps:」の通りに、app.module.tsのionic-storage
の設定を下記の通り変更する。
インポートを
import { IonicStorageModule } from '@ionic/storage'
に変更するIonicStorageModule.forRoot()
をimports: []
配列に追加する
修正前のsrc/app/app.module.ts
:
// ...省略 import { Storage } from '@ionic/storage'; // ...省略 @NgModule({ // ...省略 providers: [ {provide: ErrorHandler, useClass: IonicErrorHandler}, Storage, InAppBrowser ] }) export class AppModule {}
修正後のsrc/app/app.module.ts
:
// ...省略 import { IonicStorageModule } from '@ionic/storage'; // ...省略 @NgModule({ // ...省略 imports: [IonicModule.forRoot(MyApp), IonicStorageModule.forRoot()], // ...省略 providers: [ { provide: ErrorHandler, useClass: IonicErrorHandler }, InAppBrowser ] }) export class AppModule {}
ブラウザで動作確認(6回目):エラー
ブラウザで動作確認して、StaticInjectorError(AppModule)[ApplicationInitStatus]: StaticInjectorError(Platform: core)[ApplicationInitStatus]: NullInjectorError: No provider for ApplicationInitStatus!
エラーが発生した。
Runtime Error StaticInjectorError(AppModule)[ApplicationInitStatus]: StaticInjectorError(Platform: core)[ApplicationInitStatus]: NullInjectorError: No provider for ApplicationInitStatus! Stack Error: StaticInjectorError(AppModule)[ApplicationInitStatus]: StaticInjectorError(Platform: core)[ApplicationInitStatus]: NullInjectorError: No provider for ApplicationInitStatus! at _NullInjector.get (http://localhost:8100/build/main.js:1606:19) at resolveToken (http://localhost:8100/build/main.js:1904:24) at tryResolveToken (http://localhost:8100/build/main.js:1846:16) at StaticInjector.get (http://localhost:8100/build/main.js:1714:20) at resolveToken (http://localhost:8100/build/main.js:1904:24) at tryResolveToken (http://localhost:8100/build/main.js:1846:16) at StaticInjector.get (http://localhost:8100/build/main.js:1714:20) at resolveNgModuleDep (http://localhost:8100/build/main.js:11458:25) at NgModuleRef_.get (http://localhost:8100/build/main.js:12691:16) at http://localhost:8100/build/main.js:6103:70
app.module.tsにBrowserModuleを追加する
このサイトを参考に、app.module.ts
にBrowserModuleを追加したら、エラーが出なくなった。
src/app/app.module.ts
:
import { NgModule, ErrorHandler } from '@angular/core'; // add this! import { BrowserModule } from '@angular/platform-browser'; // ... 省略 @NgModule({ declarations: [ // ... 省略 imports: [ IonicModule.forRoot(MyApp), IonicStorageModule.forRoot(), // add this ! BrowserModule, HttpClientModule ], // ... 省略 export class AppModule {}
ブラウザで動作確認(7回目):エラー
NullInjectorError: No provider for Http!
エラーが発生した。
Runtime Error StaticInjectorError(AppModule)[XXXService -> Http]: StaticInjectorError(Platform: core)[XXXService -> Http]: NullInjectorError: No provider for Http! Stack Error: StaticInjectorError(AppModule)[XXXService -> Http]: StaticInjectorError(Platform: core)[XXXService -> Http]: NullInjectorError: No provider for Http! at _NullInjector.get (http://localhost:8100/build/main.js:1606:19) at resolveToken (http://localhost:8100/build/main.js:1904:24) at tryResolveToken (http://localhost:8100/build/main.js:1846:16) at StaticInjector.get (http://localhost:8100/build/main.js:1714:20) at resolveToken (http://localhost:8100/build/main.js:1904:24) at tryResolveToken (http://localhost:8100/build/main.js:1846:16) at StaticInjector.get (http://localhost:8100/build/main.js:1714:20) at resolveNgModuleDep (http://localhost:8100/build/main.js:11458:25) at NgModuleRef_.get (http://localhost:8100/build/main.js:12691:16) at resolveDep (http://localhost:8100/build/main.js:13181:45)
HttpClientModuleに切り替える
Angularの古いタイプのhttpを使っていることが原因だったので、HttpClientModule
に切り替えたら、エラーは解決した。
ブラウザで動作確認(8回目):エラー
webpackJsonp is not defined
エラーが発生した。
Error Close Runtime Error webpackJsonp is not defined Stack ReferenceError: webpackJsonp is not defined at http://localhost:8100/build/main.js:1:1 Ionic Framework: ^3.9.2 Ionic Native: ^2.9.0 Ionic App Scripts: 3.1.8 Angular Core: ^5.2.9 Angular Compiler CLI: ^5.2.9 Node: 8.1.4 OS Platform: macOS High Sierra Navigator Platform: MacIntel User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
index.htmlに<script src="build/vendor.js"></script>
を追加する
<script src="build/vendor.js"></script>
を<script src="build/main.js"></script>
の前に追加するとエラーは消える。
src/index.html
:
<!-- ... 省略 --> <body> <!-- Ionic's root component and where the app will load --> <ion-app></ion-app> <script src="cordova.js"></script> <!-- The polyfills js is generated during the build process --> <script src="build/polyfills.js"></script> <!-- add this! --> <script src="build/vendor.js"></script> <!-- The bundle js is generated during the build process --> <script src="build/main.js"></script> </body> <!-- ... 省略 -->
上記の対応をした段階で、全てのエラーが解決し、動作確認に成功した。