もくじ

今回のゴール

前回作成した雛形アプリのソースコードを覗いてみて、Angularアプリが動く仕組みをざっくり理解することを目指しましょう。

本記事では、ngコマンドによって隠蔽されているwebpackについての記述は割愛しています。

Angularアプリが動作する仕組み

ng serve は何をしている?

前回、ng new で作成した雛形アプリを ng serve コマンドで起動しましたね。このときアプリ内部では何が起こっているのかを簡単に確認してみましょう。

起点となっているファイルは、angular.json です。

Angularアプリのソースコードには angular.json というアプリケーション全体の設定を行うためのファイルがあり、ng serve コマンドはこのファイルで設定されている内容を元にアプリケーションを起動します。

angular.json の中を見てみると、以下のような箇所があります。

"index": "src/index.html",
"main": "src/main.ts",

これらの設定により、ng serve コマンドでアプリを起動すると、src/main.ts がエントリポイントとして読み込まれ、プログラムの実行結果が src/index.html にレンダリングされます :+1:

main.ts は何をしている?

では、その main.ts は何をしているのでしょうか。

ファイルを開いてみると、以下のような簡素なコードが書かれています。

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

ポイントは最後から2行目の

platformBrowserDynamic().bootstrapModule(AppModule)

です。

なんとなく、「AppModuleを」「ブラウザ環境向けに」「起動する」 というようなことをしているっぽいコードですね。

また、よく見ると4行目に

import { AppModule } from './app/app.module';

とあり、どうやら AppModule とやらは src/app/app.module.ts ファイルから読み込まれているようです。

import文においてファイル拡張子 .ts は省略することが可能です。

AppModule の中身はどうなっている?

少し深追いしてみましょう。

main.ts はどうやら src/app/app.module.ts から読み込んだ AppModule というものを起動するという仕事をしているようでした。

では、その AppModule の中身はどうなっているのでしょうか?実際に覗いてみましょう。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

なんだかゴチャゴチャと書かれていますね :thinking:

難しいことはよく分かりませんが、

import { AppComponent } from './app.component';
  declarations: [
    AppComponent
  ],
  bootstrap: [AppComponent]

あたりを見るに、どうやら src/app/app.component.ts から AppComponent とやらを読み込んで、それを起動するといった仕事をしていそうです。

AppComponent の中身はどうなっている?

もう少しだけ深追いしてみましょう。

src/app/app.component.ts の中身を確認すると、以下のようになっています。

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-todo';
}

やっと html とか scss とかのファイル名が出てきましたね :bulb:

試しに src/app/app.component.html の中身を覗いてみてください。やたらと長いHTMLが出てきますが、よくよく見てみると

この画面のHTMLが書かれている気がします!

つまり、

  • main.tsAppModule を起動する
  • AppModuleAppComponent を読み込んでいる
  • AppComponentapp.component.html を読み込んでいる

という構造になっているように見えますね :+1:

index.html には何が書いてある?

少し話を戻して、

ng serve コマンドでアプリを起動すると、src/main.ts がエントリポイントとして読み込まれ、プログラムの実行結果が src/index.html にレンダリングされます :+1:

と言ったうちの、src/index.html のほうには何が書かれているかを確認してみましょう。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularTodo</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

これまた簡素なHTMLですね。

ポイントは最後から3行目の

  <app-root></app-root>

です。どこかで見たことがあるぞ?と思った人は鋭い :sunglasses:

src/app/app.component.ts の中身を思い出してみましょう。

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-todo';
}

4行目に

  selector: 'app-root',

とありますね。

詳しくは分かりませんが、どうやら AppComponent が読み込んでいた app.component.html の中身は、index.html<app-root></app-root> の部分にレンダリングされる仕組みになっているようです :bulb:

モジュールとコンポーネント

ここまでで、

  1. angular.json に、src/main.ts の実行結果を src/index.html にレンダリングする、という設定が記載されている
  2. src/main.tsAppModule を読み込んで起動している
  3. AppModuleAppComponent を読み込んで起動している
  4. AppComponent で読み込んでいる src/app/app.component.html のHTMLが、src/index.html に埋め込まれる形でレンダリングされている

といった関係性が見えてきました。

Angularでは、アプリを構成する機能を モジュール という単位で分割して作成できるようになっており、1つ以上のモジュールを組み合わせることでアプリ全体を構成します。

雛形アプリでは、AppModule というモジュールが1つだけ存在しています。AppModule は、アプリ起動時に最初に読み込まれる特別なモジュールで、ルートモジュールと呼ばれます。(どんな手順で読み込まれるかは、先に読んできた通りですね :ok_hand:

また、Angularでは、HTMLテンプレート・スタイル・ロジックをひとまとめにした コンポーネント という単位でUI部品を作っていきます。作ったコンポーネントは、モジュールに登録することでそのモジュール内で利用可能になります。

雛形アプリでは、AppModuleAppComponent が読み込まれており、それが index.html に挿入されるようになっていました。この、index.html に挿入されるコンポーネントはルートコンポーネントと呼ばれます。

雛形アプリはルートモジュールとルートコンポーネントだけが存在している状態ですが、実際のアプリ開発では、自分でコンポーネントを追加したり、必要に応じてモジュールを分割したりしながらアプリを作り込んでいきます :muscle:

図にすると以下のようなイメージです。

次回予告

というわけで、今回は ng new コマンドで作成した雛形アプリのソースコードを覗いて、その構造を確認してきました。Angularアプリがモジュールとコンポーネントという単位で動いているイメージをざっくりとご理解いただけたかと思います。

次回は新しくコンポーネントを作ってアプリに組み込んでみます。

お楽しみに! :raised_hands: