Angular 2を利用するには?(実装編)Angular TIPS

初めてのAngular 2開発。誤解のしようもない最も基本的な“Hello World”を作成して、Angular 2アプリの基本構造を理解しよう。

» 2016年12月06日 05時00分 公開
[山田祥寛]
「Angular TIPS」のインデックス

連載目次

現在では、Web標準技術を利用したアプリ開発が広く普及し、そのためのフレームワークも多数存在しています。その中でも主流のフレームワークの1つである「Angular」を活用し、そのための知識を備えることには大きな意味があります。本連載は、Angularユーザーに向けて、その使いこなしTIPSを紹介するものです。なお、本連載は「Build Insider」で公開していた連載「Angular Tips」を同サイトおよび筆者の了解を得たうえで、本フォーラムに移行したものです。記事はBuild Insiderで公開した状態のまま移行しているため、用語統一などの基準が@ITの通常の記事とは異なる場合があります。


【対応バージョン】

 Angular 2。v4以降の手法に関しては「TIPS:Angularの基本構造を理解して、アプリ開発を始めるには?」を参照してください。


 別稿「TIPS:Angular 2を利用するには?(準備編)」では、Angular 2とは、に始まり、Angular 2でアプリを開発するための基本的な設定とインストールを済ませました。本稿では、準備編で作成したアプリケーションフォルダーに対して、具体的なコードを追加していきます。作成するのは、初めてのサンプルの定番――「こんにちは、世界!」を表示するだけの、基本的なサンプルです(図1)。誤解のしようもない基本的なサンプルなので、「またか」と思わず、Angular 2アプリの基本的な構造を理解してください。

図1 決められたメッセージを表示するだけのサンプル 図1 決められたメッセージを表示するだけのサンプル

【1】モジュールを準備する

 モジュールとは、アプリを構成するオブジェクト(=コンポーネント)を束ねるための仕組みです。Angular 2それ自体も複数のモジュールから構成されており、アプリの要件に応じて必要なモジュールをインポートして利用することになります。

 もちろん、モジュールはアプリ開発者が自ら定義することもできます。原則として、Angular 2アプリは、1つ以上のモジュールから構成されていなければなりません。アプリを起動する際に呼び出されるモジュールのことを「ルートモジュール」とも呼びます(いわゆる、アプリのエントリーポイントを内包するメインモジュールです)。

 以下に、その具体的なコードを示します。なお、以降のコードは特筆しない限り、アプリケーションルート配下の/appフォルダーに保存するものとします。

// [1]Angular 2で利用するモジュールをインポート
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

// [2]AppComponentコンポーネントをインポート
import { AppComponent }  from './app.component';

// [4]モジュールに関する情報を宣言
@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
// [3]モジュールクラスを準備
export class AppModule { }

リスト1 ルートモジュールAppModuleを定義するためのコード(app/app.module.ts)
各番号の内容は本文で詳しく説明します。[3][4]は順番が逆になっているので注意すること。

 まず、import命令で、Angular 2アプリを動作させるのに必要となるモジュール/コンポーネントをインポートします。

[構文]import命令

import { name,…… } from module

  • name: インポートする要素
  • module: モジュール

 [1]の@angular/〜はAngular 2が提供する標準モジュールです。最低限、モジュールを定義するためのNgModule、ブラウザー上でアプリを動作させるためのBrowserModuleをインポートしておきましょう*1

*1 あくまで最小限の構成です。本格的なアプリでは、フォームを扱うためのFormsModule、ルーティング機能を提供するRouterModuleなどもインポートの必要があります。


 [2]のAppComponentは、アプリの本体を表すコンポーネントです。後からあらためて定義します。

 そして、[3]でAppModuleという名前のルートモジュール(=モジュールクラス)を準備しています。他のモジュールから呼び出す際などには、ここで宣言した名前(AppModule)を利用します。

 ただし、これだけではモジュールと見なされません。@NgModuleデコレーターでモジュールとしての情報を宣言しておきましょう([4])。デコレーターは、モジュールやクラスなどの要素に対してメタ情報を付与するための仕組みです。Javaでいうところのアノテーションに相当する仕組み、と考えると、分かりやすいかもしれません。デコレーターには「パラメーター名: 値」のハッシュ形式で、あらかじめ決められたパラメーター情報を指定できます。

 @NgModuleデコレーターで利用できるパラメーターには、以下のようなものがあります。

パラメーター名 概要
imports 現在のモジュールで利用する他のモジュール/コンポーネント
exports 現在のモジュールで外部に公開するコンポーネントなど
declarations モジュール配下のコンポーネント
bootstrap 最初に起動すべき最上位のコンポーネント(=ルートコンポーネント
表1 @NgModuleデコレーターの主なパラメーター

 この例であれば、「BrowserModuleを参照して」「ルートコンポーネントとしてAppComponentを含んだ」AppModuleモジュールを定義する、という意味になります。

【2】コンポーネントを準備する

 手順[1]で保留にしていたルートコンポーネントを作成します。ルートコンポーネント(もしくはメインコンポーネント)とは、アプリで最初に呼び出される、いわゆるエントリーポイントです。

// [1]コンポーネントで利用しているモジュールをインポート
import { Component } from '@angular/core';

// [3]コンポーネントに関する情報を宣言
@Component({
  selector: 'my-app',
  template: '<p>こんにちは、Angular 2!</p>'
})
// [2]コンポーネントクラスを準備
export class AppComponent { }

リスト2 ルートコンポーネントAppComponentを定義するためのコード(app/app.component.ts)
  [2][3]は順番が逆になっているので注意すること。

 まず、[1]はコンポーネントを定義するためのAngular 2標準モジュールをインポートしています。

 コンポーネントの本体は[2]です。ここでは、先ほどAppModuleモジュールで指定したAppComponentという名前でコンポーネントクラスを作成しています。モジュールから参照できるよう、exportキーワードで外部に公開していることに注意してください。なお、本来であれば、classブロックの配下にコンポーネント固有のロジックを記述しますが、まずは空のままとしておきます。

 ただし、このままではコンポーネントとして動作することはできません。モジュールのときと同じく、コンポーネントの構成情報を@Componentデコレーターで定義しておきましょう([3])。Componentデコレーターでは、さまざまなパラメーターを指定できますが、ここで利用しているのは、以下の2個です*2

*2 その他のパラメーターについては、後日別稿で解説の予定です。


パラメーター名 概要
selector コンポーネントの適用先を表すセレクター式
template コンポーネントに適用するビュー(テンプレート)
表2 @Componengコンポーネントの主なパラメーター

 この例であれば、「<my-app>要素に対して、『<p>こんにちは、Angular 2!</p>』というテンプレートを適用」するためのAppComponentコンポーネントを定義したことになります。

【3】スタートアップコードを準備する

 ルートモジュールとルートコンポーネントを準備できたところで、これらを起動するためのスタートアップコードを準備します。

// [1]アプリ起動に必要なモジュールをインポート
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

// [2]モジュールを起動
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

リスト3 アプリを起動するためのコード(app/main.ts)

 まず、アプリ起動のために必要なモジュールをインポートします([1])。platformBrowserDynamicはブラウザーでアプリを起動するためのAngular 2標準モジュール、AppModuleは自分で作成したルートモジュールです(ルートコンポーネントはAppModule経由でインポートされますので、ここではインポート不要です)。

 必要なモジュールをインポートできたら、あとは、platformBrowserDynamic#bootstrapModuleメソッドでモジュールを起動します([2])。

【4】メインページを準備する

 最後に、アプリを動作するためのメインページを用意します。メインページは、(/appフォルダーではなく)アプリケーションルート直下に配置するものとします。

<html>
<head>
<title>Angular 2 TIPS</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--[1]Angular 2の動作に必要なライブラリをインポート -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!--[2]SystemJSを起動 -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<!--[3]ルートコンポーネントを呼び出し-->
<body>
<my-app>アプリをロード中です...</my-app>
</body>
</html>

リスト4 Angular 2アプリを動作するためのメインページ(index.html)

 まず、Angular 2アプリを動作させるためのライブラリをインポートします([1])。core-jsはレガシーなブラウザーのためのポリフィル(=足りない機能の穴埋め)、zone.js/reflect-metadataはAngular 2の動作に必要となるライブラリです。

 [2]ではSystemJSの設定情報(=systemjs.config.js、前回の表1と表2を参照)を読み込むと共に、System.importメソッドで/appフォルダー配下のmain.ts(正しくはmain.js)を起動しています。main.jsが無条件に読み込まれるのは、設定ファイルsystemjs.config.jsで、以下のようにappモジュール配下のメインスクリプトとしてmain.jsがひも付けられているためです。

……前略……
packages: {
  app: {
    main: './main.js',
    defaultExtension: 'js'
  },
……後略……


リスト5 SystemJSによるメインスクリプトの定義(systemjs.config.js)

 そして、[3]がルートコンポーネントを表示するための領域です。これによって、先ほど@Componentデコレーターのセレクター指定(selectorパラメーター)に合致した要素(ここでは<my-app>要素)に対して、テンプレート(templateパラメーター)の内容が反映されます。

 <my-app>要素配下には、Angular 2が初期化される前に表示されるよう、一般的にはロード待ちのコンテンツを記載しておきます(コンポーネントが処理された後は、要素配下はテンプレートの内容で置き換えされます)。

【5】アプリを起動する

 以上でアプリを起動するための準備は完了です。コマンドプロンプトから以下のコマンドを実行してください。

> npm start

> angular-quickstart@1.0.0 start C:\data\atips
> tsc && concurrently "tsc -w" "lite-server"

[1] Did not detect a `bs-config.json` or `bs-config.js` override file. Using lite-server defaults...
[1] ** browser-sync config **
[1] { injectChanges: false,
[1]   files: [ './**/*.{html,htm,css,js}' ],
[1]   watchOptions: { ignored: 'node_modules' },
[1]   server: { baseDir: './', middleware: [ [Function], [Function] ] } }
[0] 15:53:53 - Compilation complete. Watching for file changes.
[1] [BS] Access URLs:
[1]  ------------------------------------
[1]        Local: http://localhost:3000
[1]     External: http://192.168.1.7:3000
[1]  ------------------------------------
[1]           UI: http://localhost:3001
[1]  UI External: http://192.168.1.7:3001
[1]  ------------------------------------
[1] [BS] Serving files from: ./
[1] [BS] Watching files...
[1] 16.11.08 15:53:59 200 GET /index.html
[1] 16.11.08 15:53:59 200 GET /node_modules/zone.js/dist/zone.js
……後略……


リスト6 アプリを起動するためのコマンドと実行結果の例

 これによって、TypeScriptスクリプト(.tsファイル)がコンパイルされると共に、Angular 2標準の開発用サーバーlite-server)が起動して、以下のようにアプリが表示されます。この状態で、ソースコード(例えばindex.html)を書き換えると自動的にこれを認識して、ページがリロードされることも確認してみましょう。

図2 Angular 2アプリを実行した結果 図2 Angular 2アプリを実行した結果

[Note]npm startコマンド

 npm startコマンドは、package.jsonファイルで定義されたコマンドです。

"scripts": {
    "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
    "lite": "lite-server",
    ……中略……
},


リスト7 package.jsonでのコマンド定義

 ここでは、まずtscコマンドでTypeScriptスクリプトをコンパイルした後、tsc -wコマンドによる変更監視と、lite-serverコマンドによるサーバー起動を並列(concurrently)実行しなさい、という意味になります。


 以上、初めてのAngular 2アプリを実行できました。現時点でのアプリの構造を、以下にまとめておきます。

/atips …… アプリケーションルート
 ├─ /app*3
 │   ├─ main.ts …… スタートアップのためのスクリプト
 │   ├─ app.module.ts …… ルートモジュール
 │   └─ app.component.ts …… ルートコンポーネント
 ├─ /node_modules …… Angular 2で利用するライブラリ一式
 ├─ package.json …… npmの設定ファイル
 ├─ tsconfig.json …… TypeScriptコンパイラーの設定ファイル
 ├─ systemjs.config.js …… SystemJSの設定ファイル
 └─ index.html …… トップページ
図3 npm installコマンドを実行した後のアプリの構造

*3 サンプルを実行後であれば、.tsファイルと同名の.jsファイル(=コンパイル済みJavaScriptファイル)、.js.mapファイル(=マップファイル)もできているはずです。


 こうして見てみると、「簡単なアプリを動かすにもAngular 2は難しい!」と思われるかもしれません。しかし、ここまでの内容は、一般的なアプリではほぼ共通です。本稿のコードをスケルトンとして、以降のコードを追加していくようにすると、開発を効率化できるでしょう。

 本連載でも、以降、本稿のコードを前提として、そこからの差分を解説していきます。

処理対象:“Hello World” カテゴリ:基本
処理対象:ルートモジュール カテゴリ:基本
処理対象:ルートコンポーネント カテゴリ:基本
処理対象:main.ts カテゴリ:基本
API:NgModule カテゴリ:@angular > core > INTERFACE(インターフェース)|ADVANCED > Angular Modules
API:@NgModuleデコレーター カテゴリ:ADVANCED > Angular Modules
API:BrowserModule カテゴリ:@angular > platform-browser > CLASS(クラス)|ADVANCED > Angular Modules
API:@Component カテゴリ:@angular > core > Component decorator(コンポーネントデコレーター)
API:platformBrowserDynamic カテゴリ:@angular > core > platform-browser-dynamic > CONST(定数)
API:import|export  カテゴリ:TypeScript/JavaScript > 文法


「Angular TIPS」のインデックス

Angular TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。