himetani's blog

備忘録など。

Gulp.jsとBrowserSyncを使ったAngularJSアプリの快適な開発環境(2015/04)

AngularJSのそれなりの大きさのシステムを作っているのですが、今まではYoemanを使った開発フローを採用していました。

ただシステムが大きくなるにつれて管理が難しくなるし色々問題が出てきているので、Yoemanから脱却しようと一念発起して、一から開発フローを考え直しました。

結局、基本的にはGulp.jsとBrowserSyncを使って開発していくことに決めたのでどんな感じでやったのかということをまとめておこうと思います。

これを機に、ちゃんとテストを書くようにしようかなーとかも思っています。


開発しているのは、ローカルで動くようなSPA(Single Page Application)で、サーバサイドはNode.jsのExpress、フロントエンドは前述のようにAngularJSです。

これまでに使ってきたYoemanについてですが、Yo、Bower、Gruntという三つのツールで構成されているWeb開発を簡単にするためのツールです。

  • Yo:アプリケーションの雛形を自動で生成するツール。色々な雛形(Generator)が登録されているので使いたいものを探して利用すると便利です。ちなみに、使っていたのがこちら。

DaftMonk/generator-angular-fullstack · GitHub

  • Bower:JavaScriptのライブラリ等の依存関係を管理するためのツール。npmはNode.jsのパッケージを管理しますが、Bowerは主にフロントエンド用のライブラリのパッケージ管理システムてな感じだと思います。

少し古い記事ですが、詳しくはここに載っています。dev.classmethod.jp

さて、Yoemanを使って何が不便だったかということなのですが、「全体が見えない!」ということに尽きます。

先ほど紹介した、generator-angular-fullstackを使ってプロジェクトを生成すると、AngularJSの雛形、Expressの雛形、などなどアプリケーションの雛形と、念入りに設定されたGruntfile.jsができあがります。

実際に使っていたディレクトリ構造は以下のような感じです。

|── client
|   |── app // AngularJSで書かれたソースがあるディレクトリ
|   |── assets
|   |── bower_components // Bowerのライブラリのファイルの置き場所
|   |── components
|── e2e
|   |── main
|── node_modules
|── server
    |── api
    |── components
    |── config
    |── json
    |── tools
    |── views
    |── workspace

Bowerでライブラリを管理しつつ、Gruntでタスクを実行して、という感じで使っていました。

Gruntfile.jsに書かれていたタスクで使っていたのが、defaultタスクとserveタスクです。

defaultタスクは、CSS拡張言語、JSの拡張言語のコンパイルCSS、JSのminify、を行って、distディレクトリにプロダクトを生成する。
serveタスクは、index.htmlに利用する全てのCSS、JSファイルをinjectして、デバッグ用のWebサーバを起動し、ファイルが更新されると、ブラウザを自動的に更新する。

とこんな感じでした。

特にserveタスクのファイルの変更を監視してくれるのはすごく便利で、開発がすごく捗りました。

ただYoemanを使ったこの開発フローではいくつか問題点がありました。

- Generatorのコマンドを使わずにファイルを生成した場合、適切な場所にファイルを置かないと変更が反映されない。Gruntfile.jsで監視するディレクトリの位置が決まっているため。

- 自動でできたディレクトリ構成が複雑すぎて、自分でも全てを把握できていない。

- YoのGeneratorを使ってファイルを生成すると、特に使わないファイルも生成されるので、肥大化していく。

便利になるようにブラックボックス的にYoemanを使っていても、結局Gruntfile.jsを真面目に読んだり、ディレクトリを探索して設定ファイルを探して編集したりすることになるのであまりメリットを感じられなくなってしまいました。

ということで、できるだけ自分で把握できるようにしようとしているのが今回の目的です。

方針   
- さまざまなツールを組み合わせて使わないようにする
- ユーザが多く、普及しているツールを選ぶ
- 便利だったものを再現する(grunt serveでできていたこと)
- Bowerは使わない


ライブラリ管理のBowerですが、色々いらないファイルもダウンロードされてしまうのが嫌なので、ライブラリの公式からminifyされたファイルだけとってきて使うようにします。

こういう方針で色々なツールを探していたのですが、結局タスクランナーにGulp.js、ファイルの変更監視とブラウザの自動リロード機能としてBrowserSyncを使うようにしようということで落ち着きました。

基本的なディレクトリ構成はこんな感じです。

├── client
│   ├── app // Angular系のファイルの置き場所
│   ├── assets // Angular系以外のファイルの置き場所
│   └── index.html
├── e2e
├── gulpfile.js
├── node_modules
│   ├── body-parser
│   ├── browser-sync
│   ├── ejs
│   ├── express
│   ├── gulp
│   ├── gulp-angular-filesort
│   ├── gulp-inject
│   ├── gulp-jshint
│   ├── gulp-nodemon
│   ├── gulp-notify
│   └── gulp-uglify
├── package.json
└── server
    ├── app.js
    ├── config.js
    ├── express.js
    └── routes.js

この構造自体は、YoemanのGeneratorで作ったやつをめっちゃ参考にしています。
一般的な基本構造を学べるっていう点では、Generatorを一度使うのはすごくよいと思います。

appディレクトリ以下にAngularJS関連のファイルが置いているんですが、
AngularJS Best Practices: Directory Structure | Scotch

を参考にしてこんな感じで作っていこうと思っています。

app
├── app.js //mainのモジュールの設定
├── components // 一つの完結した部分のパーツの置き場所
└── shared // 再利用可能な部品

AngularJSを使う上での悩みどころの一つは、どういう風にファイルを分けるかなのですが上に紹介してるようなのが今のところは割と一般的みたいです。

作ったgulpfile.jsはこんな感じです。

gist.github.com

GulpはGrunt同じようなタスクランナーツールなのですが、昨今のNode.jsで書くような感じでシンプルに書けるのですごく使いやすいです。
(パイプでつなげて書いていく感じ、callbackの中に処理を書いていく感じとか)
BrowserSyncもすごくいいです。ブラウザを自動でリロードするツールでLiveReloadというのもあるんですが、LiveReloadよりすごくシンプルに書けます。

さて、これを起動すると
f:id:himetani:20150419030020p:plain

Nodemonというツールで、gulp上でExpressサーバを立ち上げて、BrowserSyncサーバを経由してアクセスするできます。
BrowserSyncでは、ファイルを監視していて、ファイルの更新があったときにブラウザをリロードします。

さらに立ち上げたときに表示されたUIのポートで管理画面にアクセスすることもできます。

f:id:himetani:20150419030650p:plain

現時点でなるべくシンプルに、自分の作りかった環境を作るのにはこれがベストかなーと思ってます。

他にも、依存関係のツールでWebPackっていうのもすごく便利みたいです。今回は採用しなかったけど。webpack.github.io


最後に、JavaScript周りはツールが多すぎるんですけど、

  • Githubのスター数見て流行ってそうな(ユーザが多い)のを選ぶ
  • ツールにとらわれすぎず、達成したいことが何かを整理してからツールを選択する

ことが重要なのかなー、と今回改めて思いました。

これからは、E2Eのテストを書くべく、色々と調べてみようと思います。
今のところは、github.com

が最有力候補です。