AngularJS + Onsen UI 2 + Webpack2 (+ PhoneGap) のサンプル作ってみた

Onsen UI 2 + AngularJSでアプリを作っている人ってどれぐらいいるのでしょうか？

Onsen UIの[公式ブログ](https://onsen.io/blog/)ではReact（と最近はVueかな？）が人気っぽいですね。
ES2015やWebpackといった新しいフロントエンド技術も出てきて大変勉強になります。

でも、あれ？AngularJSは？

ES2015とWebpackや組み合わせている例をあまり見かけないような...？

# 今回のサンプル
というわけで作ってみました。

https://github.com/puku0x/angularjs-onsenui2-webpack2

ES2015/ES2016とSCSS/cssnextをサポートしています。Webpackのバージョンは2.x系です。

# 必要なもの

- [Node.js](https://nodejs.org/ja/)

これだけ。Node.jsだけあれば良いです。

エディタは[Atom](https://atom.io/)か[Visual Studio Code](https://code.visualstudio.com/)を推奨。

プログラミング初心者、あるいは今後TypeScript化を考えているなら後者の方が良いかも？

# 使い方

#### リポジトリをクローン<br> 
```
$ git clone https://github.com/puku0x/angular-onsenui2-webpack2.git
```

#### 依存ライブラリをインストール
```
$ cd クローン先のディレクトリ
$ npm i
```
インストール時に管理者権限のエラーが出たときは `sudo npm install` としてください。

Yarnを使っている人は`npm`の部分を`yarn`に置き換えてください。

#### ビルド&プレビュー実行
```
$ npm start
```

ビルド後、ブラウザで http://localhost:3000 を開くとプレビューされます。
もちろん[PhoneGap Developer](https://itunes.apple.com/jp/app/phonegap-developer/id843536693)アプリもそのまま使えます。

# 仕組み

ES2016とSCSSのトランスパイルには[Webpack2](https://webpack.github.io/)を採用しました。
Webpack自体の使い方はいろんな人が情報出してくれてるのでググればなんとかなるかと。

```js:webpack.config.js
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = (env) => {
  // プラグイン設定
  const plugins = [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: 'vendor.bundle.js'
    }),
    new ExtractTextPlugin({
      filename: "bundle.css",
      allChunks: true
    })
  ];

  return {
    entry: {
      app: './src/js/app.js',
      vendor: ['angular', 'onsenui'],
    },
    output: {
      path: path.join(__dirname, '/www/assets'),
      filename: 'bundle.js',
    },
    devtool: 'inline-source-map',
    plugins,
    module: {
      rules: [{
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader']
        })
      }, {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader', 'postcss-loader', 'sass-loader']
        })
      }, {
        test: /\.(otf|eot|svg|ttf|woff|woff2)(\?.+)?$/,
        use: 'file-loader'
      }, {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: ['babel-loader']
      }
      ]
    }
  };
};
```

PhoneGapがデフォルトで`/www`をウォッチしていることを利用し、Webpackの出力先を`/www/assets`に設定することでビルド→プレビューの連携を実現しています（`index.html`で`assets/bundle.js`と`assets/vendor.bundle.js`、`assets/bundle.css`を読み込むようにしています）。

Webpack2では`ng-annotate-loader`が上手く動かないので、Babelプラグインを使って解決しています。

```json:.babelrc
{
  "presets": [
    [
      "es2015",
      {
        "modules": false
      }
    ],
    "es2016"
  ],
  "plugins": [
    "angularjs-annotate"
  ]
}
```

`package.json`のスクリプトは以下の通りです。

```json
"scripts": {
  "build": "webpack --progress --color -p",
  "webpack": "webpack --progress --color --watch",
  "serve": "phonegap serve",
  "start": "concurrently \"npm run webpack\" \"npm run serve\""
}
```

`npm start`と打つと、WebpackのビルドとPhoneGapサーバの起動が並列実行されます。

# 問題点

- ~~Onsen UI 2 が **最新版** だとうまく動かない<br>~~
~~最新版の **2.0.5** ではページ引数が一つ前のものになるバグがあります。<br>~~
~~また、 **RC.18** 以降ではons-template内のデータバインディングが機能しないバグもあります。~~
ons-initを使うことで解決。