Help us understand the problem. What is going on with this article?

Ionic3でアプリを作る際のLazy Loadingへの対応

More than 1 year has passed since last update.

最近(2018年10月)、Ionic3でAndroidアプリを作って、Play Storeで公開しました。

そこに至るにはいろいろと罠がありましたので、その記録を思い出せるうちに書いて残しておこうと思います。

困ったり解決したりする度にツイートしてたからいけるはず……!!

いくつかの記事にわけて、シリーズとしてまとめておきます。

なお、なんとかリリースできたアプリはこちら。あなたの日本語入力速度を測定します。→フリックとローマジ 〜日本語入力スピード測定〜

シリーズ一覧

この記事では、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デコレータを使って

hoge.module.ts
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用の共有モジュールの例をあげておきます。

components.module.ts
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);
...
LazyLoadingの例
//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が動かない時

詳しくはこちらに書いてあります。

https://angular.io/guide/frequent-ngmodules#browsermodule-and-commonmodule

要約すると、Lazy Loadingで読み込むモジュールの中で*ngFor*ngIfを使いたい場合は、そのモジュールのmodule.tsCommonModuleをインポートせよ、ということです。

Componentを共用モジュールで宣言している場合は、その共用モジュールのmodule.tsでそのimportを行うことになります。上記のコード例を再掲しておきますね。

components.module.ts
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版を作っていくことになるかな〜。

agajo
あんなに勉強して、親に高い予備校代も出してもらって東大に入り、卒業したのに、今では家と食事を親に頼りながら、年金と住民税を払うためにトイレ掃除をしている者です。
https://portal.oka-ryunoske.work/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした