最近(2018年10月)、Ionic3でAndroidアプリを作って、Play Storeで公開しました。
そこに至るにはいろいろと罠がありましたので、その記録を思い出せるうちに書いて残しておこうと思います。
困ったり解決したりする度にツイートしてたからいけるはず……!!
いくつかの記事にわけて、シリーズとしてまとめておきます。
なお、なんとかリリースできたアプリはこちら。あなたの日本語入力速度を測定します。→フリックとローマジ 〜日本語入力スピード測定〜
#シリーズ一覧
-
小さめの奴をまとめて
- Ionicアプリにおける、色の指定のしかた
- アプリのIDを初期値にしたまま端末に複数インストールすると上書きされる
- iconとsplashの生成
- android実機デバッグでエラーメッセージを見る
- chromeでinspectタブを開いていると、端末ビルド時にno device error
- play-services-ads v17 でAndroidManifest.xmlのmeta-data強制
-
複数のファイルにまたがるPromiseの使い方
- IonicのNavControllerはProviderからは使えない
- プライバシーポリシー
- admob-freeプラグインでのeventsオブジェクトの扱い
- firebaseプラグイン導入時のGoogle Play Services libraryのバージョン調整
- Lazy Loading への対応(この記事)
- ngIf、ngForが動かない時
この記事では、Lazy Loadingについて扱いますが、PageとComponentの場合の話だけします。PipeやDirectiveの場合については触れませんが、基本的にComponentの場合と同じです。
#Lazy Loading????
Lazy Loadingとは、アプリ内で使うモジュールを、必要な分だけ随時読み込んでいく仕組みのことです。
最初に全部いっぺんに読み込まないので、その分起動が早くなるメリットがあります。
詳しくはこちら。
Ionic and Lazy Loading Pt 1 | The Official Ionic Blog
IonicでLazy Loadingに対応する - Qiita
#Lazy Loadingの時とそうでない時のモジュール宣言の違い
AngularやIonicで使用するモジュールは、どこかでモジュールとして宣言されていなければいけません。PageとかComponentとかPipeとかDirectiveとか、全部モジュールです。
具体的には、なんとか.module.ts
というファイルの中で、@NgModule
デコレータを使って
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { HogePage } from './hoge';
@NgModule({
declarations: [//declaration(「宣言」という意味の英単語)
HogePage,//←宣言の中に「HogePage」を加える
],
imports: [
IonicPageModule.forChild(HogePage),
],
})
export class HogePageModule {}
という感じで宣言します。
この宣言を、hoge.module.ts
で独自にやるか、もっと親玉のapp.module.ts
でたくさんまとめて宣言するか、という違いが、Lazy Loadingかそうでないかの違いになります。
この宣言をごちゃ混ぜにして、一つのモジュールをapp.module.ts
とそれぞれのmodule.ts
の2箇所で宣言したりすると、エラーになります。
しかも、ionic cordova run android --device
の時はエラーにならないのに、ionic cordova run --prod --release
の段階になって初めてエラーになるので、気づきにくく、タチが悪いです。
Type Hoge in hoge.ts is part of the declarations of 2 modules: AppModule in src/app/app.module.ts and ComponentsModule in src/components/components.module.ts
##Pageのモジュール宣言
###Lazy Loading
それぞれのページについて、module.ts
ファイルがあり、そこで宣言する。
###いっぺんに読み込む
app.module.ts
で宣言
##Componentのモジュール宣言
###Lazy Loading
それぞれのコンポーネントについてmodule.ts
で宣言するか、Component用の共有モジュールcomponents.module.ts
でコンポーネントたちだけ一括で宣言する
###いっぺんに読み込む
app.module.ts
で宣言
###例
以下に、Component用の共有モジュールの例をあげておきます。
import { NgModule } from '@angular/core';
import { HogeComponent } from './hoge/hoge.component';
import { FugaComponent } from './fuga/fuga.component';
import { FooBarComponent } from './foo-bar/foo-bar.component';
import { CommonModule } from '@angular/common';//これについては後で解説します
@NgModule({
declarations: [HogeComponent,
FugaComponent,
FooBarComponent],
imports: [CommonModule],//これについては後で解説します
exports: [HogeComponent,
FugaComponent,
FooBarComponent]
})
export class ComponentsModule {}
#Lazy Loadingの時とそうでない時の、ComponentやPageの呼び出し方の違い
通常の場合、ComponentやPageを呼び出す時には、該当するものをファイルの冒頭でimportして、コード内で使います。
が、Lazy Loadingの場合は、importしようにもまだモジュールが読み込まれていないため、importに失敗します。
なので、そもそもimport文も書かず、コード内で使用する時には、文字列で指定します。
文字列でいいの!?と思ってしまいますが、それでうまくやってくれます。すごいですね。
import { HogePage } from '..hoge/hoge';
...
this.navCtrl.setRoot(HogePage);
...
//import文は不要
...
this.navCtrl.setRoot("HogePage");
...
#IonicのLazy Loading
Ionic3では、ionic generate
コマンドでpageやcomponentをgenerateすると、Lazy Loadingに対応した形でモジュール宣言が出力されます。
なので、Angularチュートリアルで勉強したようにapp.module.ts
に改めて宣言を書き加えると、二重宣言でエラーになります。
結局何もしなくていいってことですね。読み込む時にimport文を書かず、呼び出しを文字列にすることだけ気をつければOK。
Componentについては、個別にmodule.ts
が用意されるのではなく、コンポーネント用共有モジュールcomponents.module.ts
が用意されます。
#ngIf、ngForが動かない時
詳しくはこちらに書いてあります。
要約すると、Lazy Loadingで読み込むモジュールの中で*ngFor
や*ngIf
を使いたい場合は、そのモジュールのmodule.ts
でCommonModule
をインポートせよ、ということです。
Componentを共用モジュールで宣言している場合は、その共用モジュールのmodule.ts
でそのimportを行うことになります。上記のコード例を再掲しておきますね。
import { NgModule } from '@angular/core';
import { HogeComponent } from './hoge/hoge.component';
import { FugaComponent } from './fuga/fuga.component';
import { FooBarComponent } from './foo-bar/foo-bar.component';
import { CommonModule } from '@angular/common';//ここと
@NgModule({
declarations: [HogeComponent,
FugaComponent,
FooBarComponent],
imports: [CommonModule],//ここです。
exports: [HogeComponent,
FugaComponent,
FooBarComponent]
})
export class ComponentsModule {}
#おわりに
この記事は以上です。同時に、このシリーズも以上です。
次はiOS版を作っていくことになるかな〜。