Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save okunokentaro/cc47962523bf6980777e3a181bd399f7 to your computer and use it in GitHub Desktop.
Save okunokentaro/cc47962523bf6980777e3a181bd399f7 to your computer and use it in GitHub Desktop.
npm iしてAngualr 2のHello World!を書くところまで【改】
2016/03/24 にQiitaに投稿した記事のアーカイブです
---
追記160914: rc.7に対応しました、[本題はこちらから。](http://qiita.com/armorik83/items/ae737ab584012a0f5876#%E5%A7%8B%E3%82%81%E3%81%BE%E3%81%97%E3%82%87%E3%81%86)冒頭は終了したイベントの宣伝です。
---
@armorik83です。先日は私も[ng-japan](http://ngjapan.org/)に登壇してきましたが、会場内のAngular 2熱の高さに興奮を覚えたものです。
さて、私が代表を務めている[ng-kyoto](http://ng-kyoto.github.io/)とng-japan、GDG神戸、会場のteratailさん、サイボウズ株式会社さんのご協力によって、来る4/10と4/16にAngular 2ハンズオン勉強会を開催いたします。
- [4/10 Angular 2ハンズオン勉強会@渋谷ヒカリエ レバレジーズ本社](http://connpass.com/event/28985/)
- [4/16 GDG神戸 Angular 2ハンズオン勉強会@サイボウズ 大阪梅田オフィス](https://gdgkobe.doorkeeper.jp/events/40817)
これは両イベント共にng-kyotoの代表である私の他、@_likr, @shinsukeimai, @pastelInc オーガナイザらが関わっており、初のAngular 2ハンズオン東西合同開催と銘打って盛り上げております。さらにng-japanから強力なバックアップとして@can_i_do_web, @laco0416にもお手伝い頂いています。
ではなぜこれほどAngular 2を我々がプッシュするか。やはり、盛り上がってほしいからです!Angular 2はAngular 1とは打って変わってWeb標準にとても寄り添ったモダン・フレームワークです。先にWeb標準に沿って発表され一世を風靡したReactに対してAngular 1はお世辞にもモダンとは呼べませんでした。ところが2になり、ようやくイマドキらしい普通に選択しうるフレームワークとなったのです。
この辺りの、Angular 2が如何にモダンかという事情はlaco0416の[Angular 2の失敗しない始め方](http://laco0416.github.io/slides/a-way-for-happy-angular-days/#/)を一読するのが間違いないでしょう。
---
本稿は[同名の旧記事](http://qiita.com/armorik83/items/519cbc94459a87a4fbba)の改稿版です。先に告知したハンズオンでもAngular 2の導入はお伝えしていきますが、それとは別に「開発方法は見当がつくけれど最初が面倒くさい」という方も多いことでしょう。そんな方々にAngular 2を始めてもらえるよう"`npm i`するところから"紹介していくのが本稿の目的です。Angular 2はalpha, beta, rcと進むに連れて、初稿を書いた昨年12月からも様々な変化がありました。その差異を毎回の記事修正で補うには大きくなってきたことも、この改稿版を書いた理由です。
# 始めましょう
前置きが長くなりましたが、始めましょう。`npm`を用いたインストールや、`package.json`での管理には慣れているものとします。今回はビルドに[Browserify](http://browserify.org/), [webpack](https://webpack.github.io/)を使います。両方の始め方を紹介するので、慣れている方はどちらかお好みのもので進めてください。Browserifyとwebpackのどちらを使えばいいか分からない方は、Node.jsの標準のモジュールシステムに互換性のあるBrowserifyを使ってください。
SystemJSを用いた方法は公式のチュートリアルに掲載されているため、この記事では触れません。
Angular 2は[TypeScript](http://www.typescriptlang.org/)でのコーディングを前提に設計されているので、本稿もTypeScriptを使用します。ES2015やES5でも書けますが、私はTypeScriptで書くことをお勧めしています。
# 今回の環境
ビルド周りにしか使わないので、細かなバージョン違いは影響しないと思います。
```
$ node -v
v6.5.0
$ npm -v
3.10.7
```
# 公式サイト
- https://angular.io/
- https://github.com/angular/angular
# 開発環境を作る
## sandbox
Angular 2をインストールするディレクトリを作成します。名前は任意です。ここでは`angular2-sandbox`とします。
```
mkdir ~/Desktop/angular2-sandbox && cd $_
```
## インストール
まず`package.json`を作成します。`scripts`に記載した処理をビルドの際に`npm run`で実行するために必要です。
```
npm init -y
```
続いてインストールを進めていきます。
```
npm i -S @angular/{core,common,compiler,platform-browser,platform-browser-dynamic} rxjs@5.0.0-beta.12 zone.js@0.6.21 core-js
npm i -D typescript browserify
```
webpack派の方は、`npm i -D`に続けて次のように記述しましょう。
```
npm i -D typescript webpack
```
`@angular`で始まる複数のモジュールがAngular 2本体です。`{}`を用いて複数のモジュールをまとめてインストールすることができます。`rxjs`と`zone.js`はPEER DEPENDENCYとなっており、これらは手動でのインストールが必須となります。面倒ではありますが、これらはブラウザに対してのpolyfillという位置付けのため、Angular 2が依存するライブラリではなくユーザが個々でインストールする形となっています。この設計の顛末は[issues](https://github.com/angular/angular/issues/6659#issuecomment-185120027)にて確認できます。
`core-js`はTypeScriptで出力したES5ソースの中でES2015 Promise, Collectionsを動かすために必要なpolyfillです。`core-js`を含めずに`tsc -t es6`としてpolyfillを使わずに進めることも可能ですが、そのほかで煩雑な変換が求められるので本稿では割愛します。
## ビルドスクリプト
TypeScript 1.8で書くため、ブラウザで動作するJavaScriptにするためのコンパイル作業が必要です。これから作成していく各`.ts`ファイルはTypeScriptの`import`/`export`によって互いの依存関係を記述するので、最終的にはBrowserify, webpackを使用し結合します。
Angular 2公式のチュートリアルではSystemJSを推奨していますので、そちらを使っても構いません。どちらを使っても実装自体の`import`/`export`の書き方が変わるわけではありません。
`package.json`の`"scripts"`を次のように書き換えます。
```package.json
{
"scripts": {
"tsc": "tsc -p .",
"browserify": "browserify ./index.js -o ./bundle.js",
"build": "npm run tsc && npm run browserify"
}
}
```
webpackだと次のようになります。
```package.json
{
"scripts": {
"tsc": "tsc -p .",
"webpack": "webpack ./index.js --output-filename ./bundle.js",
"build": "npm run tsc && npm run webpack"
}
}
```
TypeScriptのコンパイルコマンド`tsc`では、`-p`オプションでプロジェクト・ディレクトリを指定し`tsconfig.json`にコンパイルオプションを記述するのが標準的な形式です。これくらいの量だと[gulp](http://gulpjs.com/)は使っていません。
## tsconfig.json
`tsconfig.json`を作成します。
```
touch tsconfig.json
```
```
{
"compilerOptions": {
"target": "es5",
"noImplicitAny": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": "node"
},
"filesGlob": [
"./**/*.ts",
"!./**/*.d.ts",
"!./node_modules/**/*",
"./node_modules/typescript/lib/lib.es6.d.ts"
],
"files": [
"./index.ts",
"./node_modules/typescript/lib/lib.es6.d.ts"
]
}
```
`experimentalDecorators`は[Decorators構文](https://speakerdeck.com/armorik83/es7-decorators)を有効にするためのオプションで、`emitDecoratorMetadata`は引数の型アノテーションを実装内でも扱うための出力を指定します。Angular 2の型ベースのDIのためにあるオプションだと認識しています。
それ以外のオプションについては[公式のWiki](https://github.com/Microsoft/TypeScript/wiki/Compiler-Options)を参照してください。`files`はコンパイル対象のファイルを配列で与えますが、これを毎回手書きするのはとても煩雑なので、IDEの支援や[CLI](https://www.npmjs.com/package/tsconfig-cli)を活用して、人の手では書かないようにしましょう。
なお、現在はベータ版のため本稿では触れていませんが、TypeScript 2.0からは`files`の記述法が変わり、IDEの支援やCLIを導入することなく増加する`.ts`ファイルに対応できるようになります。この方法についてはTypeScript 2.0 stableがリリースされたときに改稿する予定です。
# HTMLの作成
初期ロード時に表示するHTMLを記述する`index.html`を作成します。
```
touch index.html
```
```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello Angular 2!</title>
</head>
<body>
</body>
</html>
```
# コーディング
エントリポイントとなる`index.ts`、`NgModule`(後述)を宣言する`app.module.ts`、Componentを記述する`app.component.ts`を作成します。
```
touch index.ts app.module.ts app.component.ts
```
## index.tsにpolyfillをimportする
エントリポイントには、まずpolyfillのimport文も記述しておく必要があります。まずはここまでです。
```ts:index.ts
import 'core-js';
import 'zone.js/dist/zone';
```
## NgModuleを宣言
Angular 2では、アプリケーションを開発していく際に、まず`NgModule`という単位でclassを宣言し、そこにアプリケーション内で用いるコンポーネントやサービスを登録していくという流れで進めていきます。また、この`NgModule`はライブラリ開発者にとっても、提供するひとつのパッケージの単位として扱うことができます。
```ts:app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [
BrowserModule
],
declarations: [],
bootstrap: []
})
export class AppModule {}
```
`imports`は自分の`NgModule`に他の`NgModule`を取り込む際に使います。Angular 2が提供している各種モジュールや、サードパーティのモジュールをここに記述します。今回はAngular 2の`BrowserModule`を使います。
`declarations`には、[Directive](https://angular.io/docs/ts/latest/api/core/index/Directive-decorator.html)、[Component](https://angular.io/docs/ts/latest/tutorial/toh-pt3.html)や[Pipe](https://angular.io/docs/ts/latest/guide/pipes.html)を登録していきます。
`bootstrap`には、アプリケーションのエントリポイントとなるComponentを指定します。
## Component定義
続いてAngular 2アプリケーションのルートとなるComponentを定義していきます。Componentのためには`@angular/core`から`Component`をimportし、`@Component()`として`class`宣言の直上に記述します。
```ts:app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<hello-world></hello-world>
`
})
export class AppComponent {}
```
今回は`AppComponent`というComponentを作ります。`export class AppComponent {}`と書いた上に`@Component()`と添えます。これをDecorators構文といいます。
`@`を冠するDecorators構文はECMAScriptでは現在TC39 Proposal Stage 2、TypeScriptでは既に使用できる構文です。
`@Component()`内の各プロパティを見ていきましょう。`selector`はセレクタ、ここではComponent名を表します。[W3C](https://www.w3.org/TR/custom-elements/#concepts)の仕様に従うべきなので、要素名はキャメルケースにせず小文字のハイフンで表記すべきです。`template`は見ての通りテンプレートHTML、ここはプロパティ名を`templateUrl`とすることで外部ファイルのパスを指定できます。
## 子Componentを作る
Hello Worldを出力するComponentを作ってみましょう。前述の`AppComponent`内に書いてしまうこともできますが、せっかくなので親子構造をとってみます。
```
touch hello-world.component.ts
```
```ts:hello-world.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'hello-world',
template: `
<h1>Hello World!</h1>
`
})
export class HelloWorldComponent {}
```
このように、Angular 2ではComponentを複数記述するのも簡単です。
## NgModuleにdeclarationを追加
いま作成した2つのComponentを、先に作った`NgModule`に登録しましょう。
```ts:app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HelloWorldComponent } from './hello-world.component';
@NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent,
HelloWorldComponent
],
bootstrap: [AppComponent]
})
export class AppModule {}
```
`declarations`に作成したComponentを追加していき、`bootstrap`にはルートとなるComponentの`AppComponent`を指定します。
## エントリポイントを記述
最後にエントリポイントである`bootstrapModule`を記述します。
```ts:index.ts
import 'core-js';
import 'zone.js/dist/zone';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
```
`bootstrapModule()`の引数に作成した`NgModule`を渡します。最後にHTML側も追記します。
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello Angular 2!</title>
</head>
<body>
<my-app>Loading…</my-app>
<script src="./bundle.js"></script>
</body>
</html>
```
`<my-app>`内は読み込み後にテンプレートに置き換わりますが、ここにローディング表示を書くことも可能です。その下、`<script src="">`ではBrowserify, webpackが出力したソースを指定します。
# ビルド、そして起動
`npm`でビルドスクリプトを起動し、ビルドしましょう。
```
npm run build
```
少し待つと`bundle.js`が出力されます。あとは`index.html`をブラウザで開けば完了です!
![Screen Shot 2015-12-01 at 01.28.16.png](https://qiita-image-store.s3.amazonaws.com/0/17959/e7e96c9a-644c-af85-a6d7-19843812d055.png)
この例はまだローカル経由で動きますが、RouterやAjaxなどが絡むときはローカルでサーバを立ててください。
今回の作成の経過はコミット単位でまとめてありますので参考にしてください。
https://github.com/armorik83/qiita-npm-i-angular2/commits/webpack
---
まだまだアプリケーションからは程遠いですが、基本的には、いくつものComponentを細かく作ってはViewを組み立てていき、その後ろをドメイン層やストア層が支えるというアーキテクチャです。Fluxを参考にするのも手でしょう。
今回は公式サイトで紹介されているSystemJSを使わずにBrowserify, webpackでAngular 2を始める方法を説明しました。Angular 2もいよいよstable真近となり毎日開発が進んでいますので、今から小さいアプリ開発にチャレンジして、今後の趣味、業務に活用しましょう!
それではまた。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment