(-> % read write unlearn)

My writings on this area are my own delusion

Angular2beta の 5 min quickstart

Angularの勉強会に申し込んだので、Angular2を勉強してみることにしました。

Angularとは・・・

  • Javascriptフレームワークです。
  • Googleが開発し現在はOSSです。
  • SPA(Single Page Application)を作るのによく使われます。
  • 2.x系はこの記事を書いている現在はまだBetaです。
  • 1.x系とは、基本的に後方互換性がないです。*1

自分は業務ではサーバサイドが多く、Javascriptは専らJQuery育ちです。Backbone以降のJavascriptフレームワークにはおしなべて疎いです。 今回は、Anguluar2の5 min quickstartをやってみました。 そして自分なりにその内容を日本語でまとめてみました。理解に怪しい所が多々あるので、優しい方は指摘頂けると嬉しいです。

quickstartは3バージョンありました。

  1. Typescript
  2. Dart
  3. Javascript

自分はJavascriptバージョンをやりました。

以下、Angularという言葉をバージョンを明示しないで使っていたら全てAngular2(beta)のことです。

プロジェクトの作成

まずは、プロジェクトのディレクトリを作って、そこに移動します。
angular2-quickstartというディレクトリ名はクイックスタートそのままのディレクトリ名です。

mkdir angular2-quickstart
cd    angular2-quickstart

次に必要なライブラリをnpmでインストールするためにpackage.jsonを作ります。 npmはnode.jsのパッケージ管理ツールです。nodeをインストールするとnpmも一緒にインストールされるので、入ってない場合は brew installl nodeとかでインストールしておいてください。

ちなみに、自分の環境のnpmnodeのバージョンは以下のとおりでした。

➜  angular2-quickstart node -v
v5.8.0
➜  angular2-quickstart npm -v
3.7.3

さて、改めてpackage.jsonファイルを作ります。

touch package.json

ファイルを開いて以下のように書きます。

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "npm run lite",
    "lite": "lite-server"
  },
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.12",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "zone.js": "0.6.6"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.1.0"
  }
}

依存ライブラリをインストールします。

npm install

npm installコマンドは、先ほどのpackage.jsonの内容を読んで、./node_modulesディレクトリにインストールを粛々とやってくれます。 ちなみにnpm installのログでエラーが出てても

Scary error messages in red may appear during install. Ignore them. The install will succeed.
インストール中に真っ赤ないかついエラーメッセージを目にするかもしれない。全部無視してくれ。きっとインストールはうまくいっている。

とのことです。

➜  angular2-quickstart ls
node_modules package.json

アプリケーションの実装

アプリケーションのソースコード用のディレクトリを作ります。

mkdir app

app/app.component.js コンポーネント

コンポーネントを定義するファイルを作ります。

touch app/app.component.js

コンポーネントはAuglar2における基本的な構成要素です。Webページのパーツに対応し、ユーザにデータを表示したりユーザの操作を受け付けたりします。 コード状では、コンポーネントはビューのテンプレートを制御するクラスとして書かれます。Angularの開発ではこのコンポーネントというのをたくさん書くことになります。

ファイルを開いて以下のように書きます。

(function(app) {                                   // (3)
  app.AppComponent =                               // (2)
    ng.core.Component({                            // (1)
      selector: 'my-app',                          // <- CSSセレクタ。コンポーネントを挿入する先。ここではmy-appタグを指定している。
      template: '<h1>My First Angular 2 App</h1>'  // <- テンプレート。コンポーネントが挿入する内容。
    })
    .Class({
      constructor: function() {}
    });
})(window.app || (window.app = {}));

以下、コードを内側から見ていきます。

(1) コンポーネントスキーマ定義
    ng.core.Component({
      // ....
    })
    .Class({
      // ....
    });

ng.coreはグローバルに存在するAngularのコアの名前空間です。*2
ここでは、ng.core名前空間ComponentClassというメソッドをチェーンして呼び出すことでコンポーネントを作成しています。

通常、Angular2のアプリケーションファイルは、1つのコンポーネントをエクスポートします。 このapp/app.component.jsではAppComponentがエクスポートされます。

(2) エクスポート
  app.AppComponent =

appオブジェクトにコンポーネントを入れることで、グローバルな空間にエクスポートします。

より複雑なアプリケーションでは、AppComponentの下にさらにいくつものコンポーネントがツリー状にぶら下がることになるようです。

(3) 即時関数(IIFE、Immediately Invoked Function Expression)
(function(app) {
  // ....
})(window.app || (window.app = {}));

コードの一番外側の部分です。
appという変数を即時関数に渡しています。
即時関数は、関数がスコープを作るJavascriptにおいてよく使われるイディオム的なスコープ作成の手法です。

appが存在しない場合には空のオブジェクトに初期化しています。

app/main.js エントリポイントとなるファイル

次に、作成したこのコンポーネントを読み込むコードを書きます。

以下のように新しいファイルを作成し、

touch app/main.js

このファイルを開いて以下のように書きます。

(function(app) {
  document.addEventListener('DOMContentLoaded', function() {  // (2)
    ng.platform.browser.bootstrap(app.AppComponent);          // (1)
  });
})(window.app || (window.app = {}));
(1) bootstrap

Angularを起動するbootstrap関数を呼び出しています。
呼び出しの際にルートとなるコンポーネントを教えています。今回のルートのコンポーネントは、さっき作成したAppComponentです。

(2) bind

上記の処理を、ページの表示が終わったタイミング*3で発火するようにイベントリスナに登録しています。

index.html Angularがコンポーネントを挿しこむ場所

今まで作成したJavascriptが動作する場所を作ります。HTMLです。

touch index.html

このindex.htmlapp配下ではなく、その上のディレクトリに作ります。この時点でファイル構成は以下のとおりです。

➜  angular2-quickstart tree | head -6
.
├── app
│   ├── app.component.js
│   └── main.js
├── index.html
├── node_modules

このindex.htmlを開いて以下のように書きます。

<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">

    <script src="node_modules/es6-shim/es6-shim.min.js"></script>                      <!-- (1) ES6が使えないブラウザでES6の機能を提供するライブラリ -->
    <script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
    <script src="node_modules/angular2/bundles/angular2-all.umd.js"></script>

    <script src='app/app.component.js'></script>                                       <!-- (2) モジュールの読み込み -->
    <script src='app/main.js'></script>

  </head>

  <body>
    <my-app>Loading...</my-app>                                                        <!-- (3) コンポーネントが挿入される場所 -->
  </body>

</html>
(1)

ES6の機能を提供するライブラリを読み込んでいます。
このように最新の機能が使えないブラウザに対して最新でない機能を使って同等の機能を提供することをpolyfillと言うそうです。

(2)

さっき作ったモジュールを読み込んでいます。
app/main.jsapp/app.component.jsに依存している(利用している)ので、app/app.component.jsを先に読み込まなければいけないことに注意します。

(3)

my-appタグです。 このmy-appタグは、app/app.component.js内のコンポーネント定義の際にselectorで指定されています。 これにより、Angularが、このmy-appタグをtemplateの内容で差し替えます。

実行する

ここまでで、必要なファイルの作成が完了したので実行します。 プロジェクトのルート(appディレクトリとかindex.htmlを置いている場所)に移動し、以下のコマンドを叩きます。

npm start

Chromehttp://localhost:3000/ にアクセスして、My First Angular 2 Appと表示されていればうまくいっています。

index.htmlファイルは、通常Webサーバからクライアント(つまりブラウザ)に配信されるため、本来であればサーバを準備する必要があります。 しかし、サーバの準備は面倒だし、Angular自体を学習する際の本質ではなので、quickstartではlite-serverという簡易サーバを使っています。 このlite-serverは、npmで落としてきています。package.jsonに依存が書かれています。

app/app.component.js<h1>My First Angular 2 App</h1><h1>ほげほげ</h1>とか適当に書き換えて保存します。 lite-serverが変更を検知して自動的にブラウザが読み込まれブラウザの表示がほげほげに変わります。

lite-serverはターミナルでCTRL + cとかしてkillすれば落とせます。

実際のアプリケーションではJavascript内に静的に<h1>My First Angular 2 App</h1>と書くことはあまりなく、HTMLに挿しこむデータはサーバにリクエストして取ってくるのだと思います。

感想

コードはgithubにpushしました。

Angular2自体は、内部でどう動いてるかとか気にしなければ使い方は簡単そうでした。

*1:そこらへんは1系すらきちんと触ってきていない自分には問題なしです。

*2:ng というのは Angularの略のことなんだと思います。aNGlarです。

*3:より正確にはDOMの読み込みが全て終わったタイミング