Angular2正式版でとりあえずHello World


先日、AngularJS2の正式版がリリースされました。

私はAngular2は今年の4月くらいにちょっとTutorialを触ってみる程度のことはしていたのですが、正式版になってから触っていないのでちょっとまた触ってみることにしてみました。

やはりβ版→RC→正式版とバージョンを経ると変更も結構破壊的なものが入っています。(β版のコードはAngular2のバージョンを上げるとコンパイルエラーになってしまいます。。。)

まずはHelloWorldから、やってみましょう。

ビルド環境を作る

Node.jsの使用を前提としているので、予めインストールしておきましょう。

いまアツいJavaScript!ゼロから始めるNode.js入門〜5分で環境構築編〜

相変わらず推奨環境は、Typescript+SystemJSというエコシステムのようです。

使い慣れたWebpackを使いたい!っていう人が多数いると思いますが、まずは公式のチュートリアルと推奨構成に従い、SystemJSを使うことにします。(初めて触るものが環境周りでコケるとモチベーションが下がるので。。。)

WebPackを使いたい方は、

https://github.com/AngularClass/angular2-webpack-starter

このあたりの環境をクローンしてきて流用して始めて見ると良さそうです。

最初から見ず知らずの環境でWebpackの設定ファイルを自前でゴリゴリ書くのはしんどいですし。(一応公式にも解説はあります)

公式チュートリアルからそのままコピペします。

package.json

おなじみpackage.jsonです。

プロジェクトの依存関係と、起動スクリプトを定義します。


{
  "name": "angular-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "lite": "lite-server",
    "postinstall": "typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "typings": "typings"
  },
  "license": "ISC",
  "dependencies": {
    "@angular/common": "2.0.0",
    "@angular/compiler": "2.0.0",
    "@angular/core": "2.0.0",
    "@angular/forms": "2.0.0",
    "@angular/http": "2.0.0",
    "@angular/platform-browser": "2.0.0",
    "@angular/platform-browser-dynamic": "2.0.0",
    "@angular/router": "3.0.0",
    "@angular/upgrade": "2.0.0",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.27",
    "zone.js": "^0.6.23",
    "angular2-in-memory-web-api": "0.0.20",
    "bootstrap": "^3.3.6"
  },
  "devDependencies": {
    "concurrently": "^2.2.0",
    "lite-server": "^2.2.2",
    "typescript": "^2.0.2",
    "typings":"^1.3.2"
  }
}


tsconfig.json

TypeScript使いの方にはおなじみのアレ。

TypeScriptのコンパイルの設定を記述します。


{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}


typings.json

JavaScriptのサードパーティライブラリをTypeScriptで使用する際に必要な型定義ファイルの依存関係を管理します。

余談ですが、tsdという似たようなツールがありますがこれはすでにDeprecatedとなっています


{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160725163759",
    "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
    "node": "registry:dt/node#6.0.0+20160909174046"
  }
}


systemjs.config.js

WebPackにおけるwebpack.config.jsです。


/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',
      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      // other libraries
      'rxjs':                       'npm:rxjs',
      'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      },
      'angular2-in-memory-web-api': {
        main: './index.js',
        defaultExtension: 'js'
      }
    }
  });
})(this);


 

HelloWorldを書いてみる

まずは3つのtsファイルを作ります。

app.components.ts

Angular1はModel-View-Controllerのアーキテクチャでしたが、Angular2はコンポーネント指向の設計となっています。

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

@Component({
    selector: 'my-app',
    template: '<h1>My Second Angular App</h1>' //<を全角に直してください。Wordpressのバグなのか、半角<を使うと自動的に改行が入ってしまう。。。
})
export class AppComponent {

}

まずはHelloWorldなので、AppComponentクラス自体は何もフィールドやメソッドを定義していません。

「Componentを呼び出すセレクタ」、「Componentを呼び出したときにレンダリングされるhtml」、「Componentの挙動」が一箇所に集約される形となります。(templateの中身やComponentの挙動の実装は別クラスに分離することもあります)

Angular1系だと、自作ディレクティブを駆使しないとできなかった構造ですが、Angular2ではこれが標準となっています。

Angular1系を今まで使っていた方は少し頭の切り替えが必要になるかもしれません。

React系を触っていた方にはおなじみの設計かもしれませんね。

app.module.ts

アプリケーションのモジュールを管理するtsファイルです。

先程作成したAppComponentをAngularの依存関係に乗っけています。

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

import {AppComponent} from './app.component';
@NgModule({
    imports: [BrowserModule],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule {
}

main.ts

mainファイルです。

このサンプルにおいての役割はシンプルで、AppModuleを呼び出して起動してるだけです。

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

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

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

次に、index.htmlとstyles.cssを書きます。

index.html


<html>
<head>
    <title>Angular QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">
    <!-- 1. Load libraries -->
    <!-- Polyfill(s) for older browsers -->
    <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. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function (err) {
            console.error(err);
        });
    </script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>


body部分を見てみると、AppComponentで定義しているmy-appセレクタを呼び出しているのがわかります。

styles.css

あまり本質的な部分ではないですが、CSSも定義しておきます。

/* Master Styles */
h1 {
    color: #369;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 250%;
}

h2, h3 {
    color: #444;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: lighter;
}

body {
    margin: 2em;
}

アプリケーションを起動

npm start

でHello Worldアプリケーションを起動できます。localhost:3000にアクセスしてみましょう。