[知ってたhtml/css/jsとは別物] Angular2-seedからみるイマドキのフロントエンド開発

スクリーンショット 2015-12-14 18.31.44

Angular2を追いはじめまして、「Angular2のフォルダ構成とかどうすべきかな、Angular1時代はAngular-seedがあったけど」と思い調べてみると、まだAlpha版にも関わらず「Angular2-seed」がすでにGithub上で公開されているのですね。
そのファイル群であったり、構成、開発スタイルをみていると、イマドキのフロントエンド開発についていろいろと知見を得ることができたので、まとめてみます。
 
この記事は、関西フロントエンドUG Advent Calendar 2015の14日目の記事です。

コンパイルの鬼

「angular2-seed」をインストールし、起動してみると、以下のようなフォルダ構成になっています。

angular2-seed/
├── app/           // 開発フォルダ
├── dist/          // 公開フォルダ。app/の中身をコンパイルして表示
├── node_modules   // module群
└── tools/         // コンパイルやタスクランナーの設定など

開発を進めるためには、tools/ でコンパイルやタスクランナーの設定を行った上で、app/ でいろいろ開発を行います。そしたら、タスクランナーがapp/ の中身を精査して、 dist/ にコンパイル結果を出力してくれます。
開発する上で、dist/ はあくまでコンパイル先なので、dist/ に手を入れることはありません。sassを使っていて、生成されたstyle.cssを直接変更しますか?
しませんよね。それがフォルダとなったと思って下さい。
 
つまりはですね、画像をアップロードしたい時があるじゃないですか。その場合、app/ に画像を設置したら、コンパイルが行われまして、dist/ にその画像がコピーされるわけです。もちろん、sassを設置したらコンパイルされたcssがdist/ にできます。
 
「全ての公開ファイルは、コンパイラーを通る」というわけです。コンパイルの鬼。何でもコンパイル。
 
これってPHPerでweb開発をしていた私にとっては結構驚きな開発スタイルです。rubyやPHPのようにコンパイルレスな言語をさわってた人にとっては、書いたコードはそのまま公開されるものでした。sassが登場しましたが、言っても一部をコンパイルするだけのものだったので「そういうものなんだ」と。
しかし、これはhtmlもcssもjsも画像ファイルも動画ファイルも音声ファイルも(ただのコピーとしても)コンパイラを通すわけで、場合によってはその設定で画像サイズの最適化とか、そういうことが行われるわけです。
 
なんか、「そういうものだ」といわれたらそれまでなのですが、まずここで第一のカルチャーショック。
 

何でもとりあえず「npm install」

PHPerは、composerを使うのが当たり前となりました。言わずとしれた、依存性解決とバージョン管理のためのパッケージ管理ソフトですよね。
 
フロントエンドでも、パッケージ管理ソフトはありまして、Angular2-seedでは、npmのパッケージ管理機能を使っています。これが、まさにフロントエンドのパッケージ管理なのです。
つまりは、jsのみならず、html/cssも管理しちゃう。具体的には、Angular2はもちろんのこと、AltJSの変換に必要なes6-shimや、CSSフレームワークであるBootstrapとか、Foundationとか、iconフォントのfont-awesomeとか、そういうものも全て「npm install」で入れます。入れるものらしいです。
 
今まではzipで入れてくるのが当たり前で、バージョン管理といっても後方互換ほとんどなかったじゃんCSSフレームワーク……と思っても、これらもバージョン管理されるものらしいです。
 
ちなみに、以下みたいな感じ。うん、これだけみたら、jsonでパッケージ管理してるcomposerと何ら変わりはないのですが、なんかcssフレームワークをパッケージ管理するという衝撃があった・・・。

  "dependencies": {
    "angular2": "2.0.0-alpha.52",
    "bootstrap": "^3.3.5",
    "es6-module-loader": "^0.17.8",
    "es6-shim": "^0.33.6",
    "font-awesome": "4.5.0",
    "font-awesome-webpack": "0.0.4",
    "foundation-cli": "2.0.1",
    "foundation-sites": "6.0.5",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-alpha.14",
    "systemjs": "^0.19.4",
    "zone.js": "0.5.8"
  }

 
ちなみに、今までは、apacheやmysql、phpなどはyumなどのサーバサイドのパッケージ管理が行われ、phpはconposerでパッケージ管理が行われ、タスクランナー系はcronで書いて、などしていました。
けれど、jsフレームワークをnode.jsで動かして、gulpでタスクランナー走らせるとかやりだすと、パッケージ管理はサーバサイドからフロントエンドまで全て同じところで行いますので、以下みたいなことになります。
 
全てjs化ってすごい。
 

{
  "name": "angular2-seed",
  "version": "0.0.0",
  "description": "Seed for Angular 2 apps",
  "repository": {
    "url": "https://github.com/mgechev/angular2-seed"
  },
  "scripts": {
    "build.dev": "gulp build.dev",
    "build.dev.watch": "gulp build.dev.watch",
    "build.prod": "gulp build.prod --env prod",
    "build.test": "gulp build.test",
    "build.test.watch": "gulp build.test.watch",
    "docs": "npm run gulp -- build.docs && npm run gulp -- serve.docs",
    "gulp": "gulp",
    "karma": "karma",
    "karma.start": "karma start",
    "lint": "gulp tslint",
    "postinstall": "tsd reinstall --clean && tsd link && tsd rebundle && gulp check.versions && gulp postinstall",
    "reinstall": "rimraf node_modules && npm cache clean && npm install",
    "start": "gulp serve --env dev",
    "serve.dev": "gulp serve --env dev",
    "tasks.list": "gulp --tasks-simple",
    "test": "gulp test",
    "tsd": "tsd"
  },
  "author": "Minko Gechev <mgechev>",
  "license": "MIT",
  "devDependencies": {
    "async": "^1.4.2",
    "chalk": "^1.1.1",
    "connect-livereload": "^0.5.3",
    "del": "^1.1.1",
    "express": "~4.13.1",
    "extend": "^3.0.0",
    "gulp": "^3.9.0",
    "gulp-concat": "^2.5.2",
    "gulp-filter": "^2.0.2",
    "gulp-inject": "^1.3.1",
    "gulp-inline-ng2-template": "^0.0.7",
    "gulp-load-plugins": "^0.10.0",
    "gulp-minify-css": "^1.1.6",
    "gulp-minify-html": "^1.0.3",
    "gulp-plumber": "~1.0.1",
    "gulp-sass": "^2.0.4",
    "gulp-shell": "~0.4.3",
    "gulp-sourcemaps": "~1.5.2",
    "gulp-template": "^3.0.0",
    "gulp-tslint": "^3.3.0",
    "gulp-tslint-stylish": "^1.0.4",
    "gulp-typescript": "~2.8.2",
    "gulp-uglify": "^1.2.0",
    "gulp-watch": "^4.2.4",
    "jasmine-core": "~2.3.4",
    "karma": "~0.12.37",
    "karma-chrome-launcher": "~0.2.0",
    "karma-ie-launcher": "^0.2.0",
    "karma-jasmine": "~0.3.6",
    "karma-mocha-reporter": "^1.1.1",
    "karma-phantomjs2-launcher": "^0.3.2",
    "merge-stream": "^1.0.0",
    "open": "0.0.5",
    "reflect-metadata": "^0.1.2",
    "rimraf": "^2.4.3",
    "run-sequence": "^1.1.0",
    "semver": "^5.0.3",
    "serve-static": "^1.9.2",
    "slash": "~1.0.0",
    "stream-series": "^0.1.1",
    "systemjs-builder": "^0.14.8",
    "tiny-lr": "^0.2.1",
    "traceur": "^0.0.91",
    "ts-node": "^0.5.4",
    "tsd": "^0.6.4",
    "typedoc": "^0.3.12",
    "typescript": "~1.7.3",
    "typescript-register": "^1.1.0",
    "yargs": "^3.25.0",
    "zone.js": "^0.5.8"
  },
  "dependencies": {
    "angular2": "2.0.0-alpha.52",
    "bootstrap": "^3.3.5",
    "es6-module-loader": "^0.17.8",
    "es6-shim": "^0.33.6",
    "font-awesome": "4.5.0",
    "font-awesome-webpack": "0.0.4",
    "foundation-cli": "2.0.1",
    "foundation-sites": "6.0.5",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-alpha.14",
    "systemjs": "^0.19.4",
    "zone.js": "0.5.8"
  }
}

 

htmlもcssも、jsで扱うぜ!

そう、全てjs化なのです。当然、htmlもcssもjs化が行われます。何をいってるかよくわからないけど、そういうことです。
 
例えば、Angular2でのviewの出力ですが、こんな感じで行います。
 

import {Component} from 'angular2/angular2';

@Component({
  selector: 'home',
  templateUrl: './components/home/home.html',
  styleUrls: ['./components/home/home.css']
})
export class HomeCmp {}

 
home.htmlをテンプレートとして呼び出して、styleUrlsでhome.cssを適応します。そして、home.htmlにあるAngular2的コードを変換するとかよろしくして、出力を行います。styleUrlsで呼び出されたcssはコンポーネント化がされますので、グローバル空間には影響しません。当然、jsもラッピングしている分はグローバル空間に影響しません。
 
以前は、htmlでjsを読み込む世界でした。主従関係でいうと、htmlがメインだったわけです。しかし、イマドキはそれが逆転して、jsでhtmlを読み込むようになりました。
 
もう何というか、世界観が一転した感じがします。
 

まとめ

「知ってるhtml/css、javascriptと、何か違う」というのが、Angular2-seedをさわってみての感想でした。
でもそれが結構現状のフロントエンド界隈を表しているといいますか、昔からのエンジニアは、今きているフロントエンド界隈の活性化を「今までの延長線上にあるもの」と思っているんだと思います。もちろん、それは間違いではないのですが、今までのソフトウェア開発知見をいろいろmixしたことによって似て非なるものがきている感じがします。
 
それでは、また。

お問い合わせ