本資料はDartのウェブ開発の公式ページのなかのDart開発ツールとクイックスタートのページを中心に作成してあります。不明な個所は原文を参照願います。
この概説で使われているサンプル・プログラムのコードはGitHubからダウンロードできます。またライブで試すこともできます。更に筆者による「プログラミング言語Dartの基礎」の添付資料のdart_code_samplesのappsにも同じものがangular2_quickstartとして含めてありますので、すでにdart_code_samplesが自分のIDE上にある場合はそちらも使えます。
本資料を読む前に「プログラミング言語Dartの基礎」等でDart言語の基礎知識を理解しておくことをお勧めします。
またIDEとしてIntelliJを使う場合は「AngularDartの開発環境をつくる」の章、あるいは「プログラミング言語Dartの基礎」の16.2節のなかの「AngularDartのパッケージ」を参照願います。
本資料ではOSには64ビットWindowsを、IDEにはIntelliJ IDEAのCommunity版を使用しています。
AngularはHTMLとJavaScriptまたは他のJavaScriptに変換される言語(DartまたはTypescript)を使ってクライアント・アプリケーションを構築するためのオープンソースのJavaScriptフレームワークで、グーグルとユーザ・コミュニティによって開発されており、既に馴染みの読者も多いと思います。Angularは現在Angular 2と発展しております。Angular DartはAngularJSのDart版です。AngularJSは動的ビューに重きが置かれたMVCモデルの実装であり、日本語の解説も多いので、そちらも参考になります。
Angular DartはAngular TypeScriptとともにGoogleのチームたちによって開発されています。 AngularDartはangular2パッケージとして公開されており、他のDartのパッケージ同様Pubツールを使って利用できます。
Angularアプリケーションはコンポネントたち(components)で構成されています。コンポネントはHTMLテンプレートとコンポネント・クラスの組み合わせで、スクリーン上のある部分を制御します。以下は簡単な文字列を表示するだけのコンポネントのサンプルです:
|
import 'package:angular2/core.dart'; @Component(selector: 'my-app', template: '<h1>Hello {{name}}</h1>') class AppComponent { var name = 'Angular'; } |
このアプリを何もインストールすることなく試してみましょう。QuickStart example (ソース・コードを見る) を開いてください。
各コンポネントは@Component
アノテーションで始まります。このアノテーションではHTMLのテンプレートとコンポネント・クラスがどのように一緒になって機能するかが書かれています。
selector
プロパティはAngularに対しindex.htm
のなかのカスタムの<my-app>
タグの内側にこのコンポネントを表示するよう伝えています。
|
<my-app>Loading AppComponent content here ...</my-app>
|
”Loading....”というテキストはAngularが走ってそこを埋めるまで表示されます。
template
プロパティは<h1>
ヘッダのなかのメッセージを指定しています。このメッセージはで"Hello"始まり{{name}}
で終わっています。この2重波括弧で囲った箇所はAngularの内挿バインディングの式です。実行時にはAngularはこの{{name}}
をこのコンポネントのプロパティname
の値で置き換えます。内挿バインディングはこの資料の中で見つけるであろう多くのAngularの特徴のひとつです。
AngularDartの開発環境をつくるで説明したIDEのIntelliJ CE( IntelliJ Community edition)を使ってこのアプリを覗いてみましょう。
最初にGitHubにあるquickstartを開きます。
Clone or downloadのボタンをクリックしてこのアプリの圧縮ファイルをダウンロードする
IDE上でこのファイルをエクスプローラ上で展開しフォルダの名前をquickstartに変更する
File → Openでこのフォルダを選択する
そうすると次のように表示されるはずです。
もし”Enable Dart support”というメッセージが表示されていたら、そのリンクをクリックします
もし"'Pub get'has not been run”というメッセージが表示されていたら、Get dependenciesのリンクをクリックします。このコマンドの実行にはしばらく時間がかかります
それでもIDE上でエラーが表示されている場合は、Repair cashe..を実行してみてください(これも時間がかかります)
このファイル構成はPubが追加したフォルダたちが含まれているが、もともとのファイル構成は以下のようになっています。
|
ディレクトリ・パス |
名前 |
内容 |
1 |
quickstart\web\ |
index.html |
この場合はウェブ・アプリケーションであるので、そのページを構成する総ての内部リソースがwebというフォルダに収容される。 |
2 |
styles.css |
||
3 |
main.dart |
||
4 |
quickstart\lib\ |
app_component.dart |
このアプリのコンポネントやサービスなどをライブラリとして収容 |
5 |
quickstart\ |
pubspec.yaml |
使用する外部ライブラリを指定する |
6 |
README.md |
このプログラムを解説したマークダウン形式のファイル |
|
7 |
LICENSE |
MITライセンスを記述したテキスト・ファイル |
この構成はAngularDartを使ったウェブ・アプリケーションのひな型でもあります。各ファイルのより詳細は後で説明します。
この状態でパッケージ・ビュー上のindex.htmlファイルを選択し、左クリックしてOpen in Browserを選択、次にDartiumを選択・実行させると下図のようにその結果が表示されます。あるいはコード・ビュー上にこのファイルを表示させると下図のように開きたいブラウザをアイコンで選択できます。一番右のアイコンがDartiumです:
Dartiumで開いたquickstartは次のようになります:
最初はアクセスに時間がかかりますが、これはIDEがHTTPサーバとして機能するためのPub Serveが起動し、必要な処理をするためです。IntelliJではPub Serveの動作はコンソール出力で知ることができます。
また他のブラウザを選択すると、dart2jsで変換された.jsファイル(キャッシュされIDE上には表示されない)が呼び出れ、同様な表示が得られます。この場合はDartからJaveScriptへの変換のため更に時間を要します。
ここでは各ファイルの中身をやや詳しく解説します。
このアプリケーションに必要なライブラリ・パッケージの取り込みを記述したものです。YAML(ヤムル)の書式ではその行の最初の'-'は配列であることを理解すればこの記述の理解が早いでしょう。pubspec.yamlの記述の詳細はDart解説書の「pubspecの書式」の節を参照のこと。Angular2アプリケーションではangular2とbrowserが依存物(dependencies)としてかならず記述されていなければならなりません。またそのアプリケーションが使う他のパッケージやdart_to_js_script_rewriter といった変換機(transformers)も記述します。
name: angular2_quickstart description: QuickStart version: 0.0.1 environment: sdk: '>=1.19.0 <2.0.0' dependencies: angular2: ^2.0.0 dev_dependencies: browser: ^0.10.0 dart_to_js_script_rewriter: ^1.0.1 transformers: - angular2: platform_directives: - 'package:angular2/common.dart#COMMON_DIRECTIVES' platform_pipes: - 'package:angular2/common.dart#COMMON_PIPES' entry_points: web/main.dart - dart_to_js_script_rewriter |
Angular2のアプリケーションをDartiumではなくて一般のブラウザでアクセスできるようにするにはAngular2変換機(Angular transformer)を使用しなければなりません。この変換機はDartのコードを分析し、リフレクションを使ったコードをstaticなコードに変換し、Dartのビルド・ツールがより高速でコンパクトな JavaScriptにコンパイルできるようにしているものです。- angular2:の箇所でAngular2変換機の設定を行っています。 entry_points:の記述はこのアプリのエントリ点を指定することで bootstrap.dartがインポートされたときにdart:mirrorsを使わなくするようにしています。dart:mirrorsが使われるとJavaScriptにコンパイルされたときに性能上の問題をおこすからです。
またdart_to_js_script_rewriterは該アプリケーションの性能を改善させるためにHTMLファイルに生成したJavaScriptを直接含めてしまうものです。
import 'package:angular2/core.dart'; @Component(selector: 'my-app', template: '<h1>Hello {{name}}</h1>') class AppComponent { var name = 'Angular'; } |
各Angularアプリケーションは少なくともひとつの慣習的に AppComponent と名付けられたルート・コンポネント(root component)を持っていなければなりません。このルート・コンポネントがクライアントのユーザ経験を収容するものです。コンポネントはAngularアプリケーションの基本的な構成要素です。コンポネントはそれに結び付けられたテンプレートを介してそのスクリーンのある部分(ビュー)を制御します。
このQuickStartというアプリケーションは極めて単純なコンポネントただ一つのみ持っているものですが、これは今後アプリケーションを開発する際に必ず記述することになる必須の構造となっています:
Angularに対してどのテンプレートを使用するか、及びどのようにそのコンポネントを生成するか等を知らせる為の@Componentアノテーション
そのテンプレートを介してあるビューの見た目と挙動(appearance and behavior)を記述したcomponentクラス
Import文:
Angularアプリケーションはモジュール構成になっています。各アプリケーションは各々がある目的のために特化した多くのファイルで構成されます。Angular自身もモジュール構成になっています。各々が我々が自分たちのアプリケーションのために使うことになる幾つかの関連した機能たちで構成されているライブラリ・モジュールたちの集積です。
あるモジュールあるいはライブラリから何かが必要になったときはそれをインポートすることになります。
このサンプルでは Angular 2のコアをインポートしており、これにより我々が記述しているコンポネントのコードが@Componentアノテーションにアクセスできるようになっています:
import 'package:angular2/core.dart'; |
@Componentアノテーション:
@Componentはコンポネント・クラスとメタデータを結び付けるできるようにするアノテーションです。このメタデータはAngularに対しこのコンポネントをどのように生成しまた使用するかを伝えます。
@Component( selector: 'my-app', template: '<h1>Hello {{name}}</h1>') |
@Componentコンストラクタ呼び出しにはセレクタ(selector)とテンプレート(template)の2つの名前付きのパラメタたちを有します。
selectorは該コンポネントを表現するHTML要素のためのシンプルなCSSセレクタを指定しています。このコンポネントに対する要素は my-appと名付けてあります。AngularはホストしているHTMLの中でmy-appに出会ったときはAppComponentのインスタンスを生成し、表示します。
templateは該コンポネントのテンプレートを指定しており、Angularに対しこのコンポネントのビューをどのように表示するかを強化HTMLの書式で書かれている。このサンプルでは"Hello Angular"を表示する1行のテンプレートとなっている。
テンプレートにはコンポネントのプロパティとバインドするデータや、それ自身のテンプレートを持っている他のアプリケーションコンポネントを特定するデータが含まれ得ます。これらのテンプレートは更に他のコンポネントを特定することもあります。ここでは2重波括弧で囲まれた変数nameがバインドのひとつである文字列内挿として記述されています。nameの値は’Angular’という文字列のオブジェクトです。
Componentクラス
このファイルの最後はAppComponentという名前の何もしないクラスが置かれています。
class AppComponent {} |
より大きなアプリケーションが書けるようになれば、このクラスをプロパティたちとアプリケーション・ロジックで拡張すればよいのです。この QuickStartは何もしなくてよいので空のままになっています。
import 'package:angular2/platform/browser.dart'; import 'package:angular_quickstart/app_component.dart'; void main() { bootstrap(AppComponent); } |
このアプリケーションの立ち上げに必要な2つのものをインポートしています:
Angularのブラウザ・ブートストラップ機能
このアプリケーションのルート・コンポネントである AppComponent
ブートストラップはプラットホーム依存:
angular2/core.dartからではなく angular2/platform/browser.dartからブートストラップ関数をインポートしていることに注意してください。このアプリケーションのブートストラップは単一の手段ではないのでブートストラップはコアではありません。実際ブラウザ内で走るほとんどのアプリケーションはこのライブラリからブートストラップ関数を呼び出しています。
しかしながら他の環境でコンポネントをロードすることは可能です。 モバイル機器上ではApache Cordovaあるいは NativeScriptでロードします。立ち上げを高速化したりSEO(Search Engine Optimization)を活用したりするのにサーバ上で自分たちのアプリケーションの最初のページを表示したい場合もあるでしょう。これらの場合はそれに対応したブートストラップ関数が必要であり、これらの場合には別のライブラリからインポートすることになります。
どうして main.dartとアプリケーション・コンポネントを別々のファイルとするのか?:
ここでのmain.dartとコンポネントのファイルはともに小さなものです。これは QuickStartという初歩的な教材であるからです。これらは一つのファイルに合体でき、複雑化してくれば分離させてもかまいません。
ここではAngularのアプリケーションの適切な構成を示すためにこうなっています。合体すると今後困難を生じる可能性があるからです。我々は別々のブートストラップを使う幾つかの環境でAppComponentを使う場合もあります。そのアプリケーション全体を走らせるよりそのコンポネントをテストしたほうがずっと簡単です。そのために多少手間をかけるほうが正しい手法といえます。
index.htmlファイルはそのアプリケーションを収容したウェブ・ページを定義しています。Angularがmain.dartのなかでブートストラップ関数を呼びだすと、それが AppComponentメタデータを読みだし、my-appセレクタを見つけ、my-appという名前の要素を特定し、それらのタグ間のビューを表示します。
<!DOCTYPE html> <html> <head> <title>Hello Angular</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"> <script defer src="main.dart" type="application/dart"></script> <script defer src="packages/browser/dart.js"></script> </head> <body> <my-app>Loading AppComponent content here ...</my-app> </body> </html> |
最小限のスタイルは次のようなものとなりましょう(英語圏用ですが):
<!DOCTYPE html> <html> /* 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; } |
サンプルにあるstyles.cssファイルはより高度なものになっています。
Dart言語で書かれたウェブ・アプリケーションは、DartのVMを実装したDartium以外のブラウザからは直接アクセスできません。その為にPub buildというコマンドが用意されており、そのコマンドで得られたフォルダをウェブ・サーバに配備すれば、どのブラウザからでもアクセス可能となります。
このアプリケーションをウェブ・サーバ上に配備するにはどのブラウザでも使えるようにJavaScriptファイルを生成する必要があり、それには pub buildコマンドが便利です。
OKをクリックすれば、例えば次のように変換で行われます:
Working dir: C:\Users\Terry\Downloads\quickstart-master\quickstart C:\dart\dart-sdk\bin\pub.bat build --mode=release --output=build Loading source assets... Loading angular2/transform/codegen and dart_to_js_script_rewriter transformers... Loading angular2 transformers... Building angular_quickstart... [Info from Dart2JS]: Compiling angular_quickstart|web/main.dart... [Info from Dart2JS]: Took 0:00:26.889629 to compile angular_quickstart|web/main.dart. Built 949 files to "build". Process finished with exit code 0 |
次の図はその結果生成されたbuildディレクトリの構成です:
このフォルダを配備用に使えばよいのです。例えばこのフォルダ内のindex.htmlファイルのパスをコピーし、Chromeでこれを読みだすと次のように正しく表示されます:
AngularアプリケーションのJavaScriptを生成するためにはAngularの変換機(Angular transformer)を使用します。これはDartのコードを調べ、reflectionが使われているコードをstaticなコードに変換し、Dartのビルド・ツールがより高速でより小規模なJavaScriptにコンパイルできるようにしています。
entry_pointsという項目はmain()関数を有しているDartファイルを指定しています。詳細はAngular transformerのwikiページを参照のしてください。
アプリケーションの性能改善のためにはHTMLファイルが生成されたJavaScriptを直接含むようにすれば良いのです。そのひとつの手段は dart_to_js_script_rewriterを使うことです。この書き換えプログラムはpubspecのなかの dependenciesと transformersの2か所で指定されています。