Angular2の各コンポーネントのディレクトリ構造保ちつつ、bundle.jsを作る設定方法

Angular2を書いてて、各コンポーネントごとにmain.tsを作って、tscして、さらにwebpackでbundle.jsを作りたくて、うまくいかなかったけど、最近やっと上手くいったので、個人用にメモしておきます。

## 前提

 - やりたいこと: 各コンポーネントのディレクトリ構造を保ったまま、build/各コンポーネントディレクトリ名/bundle.jsを作りたい

僕はAngular2を使うにあたってTypeScriptで書いていて、webpackを使っています。 また、tsconfig.jsonのfilesの部分をgulpのプラグインを使って更新をしています。

## 準備

webpackのインストール
gulpのインストール
gulp-tsconfig-updateのインストール
で多分いける。

gulp-tsconfig-updateは@laco0416さんが作られたgulpのプラグインで、tsconfig.jsonのfilesの部分をgulpで更新できるので、今回すごく助かりました。 記事は、[Qiita](http://qiita.com/laco0416/items/a51b7534ddc4aec63875)の記事で書かれているので、参考にしていただければと思います。

## 流れ

1. gulpfile.jsにタスクを書き込む
2. gulp実行で、tsconfig.jsonを出力
3. tsc -p . で、tsファイルをjsファイルに変換
4. webpack で各コンポーネントのbundle.jsを出力

## どうするか

準備に必要なものはインストールされた前提で話を進めます。

- まず、gulpfile.jsを作成し以下のコードを書きます。

```js
ファイル名: gulpfile.js


var gulp = require("gulp");
var tsConfig = require('gulp-tsconfig-update');
gulpfile.js

gulp.task('default', ['tsConfig']);

gulp.task('tsConfig', function() {
return gulp.src([
  "node_modules/typescript/lib/lib.es6.d.ts",
  "./app/**/main.ts"
]).pipe(tsConfig());
});
```

gulp.src()の配列の中の**(アスタリスク2つ)は、"app配下の全て" という意味です。 これで、いちいちコンポーネントを作っては、tsconfig.jsonのfilesにファイルパスを書かなくて済みます。

- gulpコマンドを実行

gulpを実行すると、先ほど書いたgulpのタスクが走って、tsconfig.jsonが出力されます。 出力された内容はこんな感じ。

```js
ファイル名: tsconfig.json


{
  "compilerOptions": {
  "target": "es5",
  "module": "commonjs",
  "moduleResolution": "node",
  "outDir": "build",
  "rootDir": "app",
  "sourceMap": true,
  "emitDecoratorMetadata": true,
  "experimentalDecorators": true,
  "removeComments": false,
  "noImplicitAny": true,
  "suppressImplicitAnyIndexErrors": true
  },
  "filesGlob": [
    "./**/*.ts",
    "!./**/*.d.ts",
    "!./node_modules/**/*",
    "./node_modules/typescript/lib/lib.es6.d.ts"
  ],
  "files": [
      "node_modules/typescript/lib/lib.es6.d.ts",
      "app/component-a/main.ts",
      "app/component-b/main.ts"
  ]
}
```

ちなみに、files以外のオプションは自分で書いています。 最初、オプションのrootDirを設定していなくて、tscでビルドされた際にコンポーネントのフォルダ構造が保たれないまま、ビルドされていたので、rootDirを設定するのが肝です。

outDirはビルドしたファイルをどこに出力するかを変更できるので、今回は"build"を指定しています。

オプションの一覧は、この[記事](http://qiita.com/IganinTea/items/3056f1b5d1c96aa733d4)とか読んでみると良いかもです。

- webpack.config.jsを編集する

webpack.config.jsは以下のように編集しました。

```js
ファイル名: webpack.config.js

var webpack = require("webpack");
var path = require("path");
var glob = require("glob");
var HtmlWebpackPlugin = require('html-webpack-plugin');

var entries = {};
glob.sync("./build/**/main.js").map(function(file) {
  let matchResult = file.match(/\/build\/(.*?)\/.*/);
  let subscript = matchResult[1] + "/" + "bundle";
  entries[subscript] = file
})

console.log(entries);

module.exports = {
entry: entries,

output: {
  path: path.join(__dirname, "test"),
  filename: "[name].js"
},

resolve: {
  root: __dirname,
  extensions: ['', '.webpack.js', '.web.js', '.js', '.ts']
},


module: {
  loaders: [
    {
      test: /\.ts$/,
      loaders: ['ts', 'angular2-template-loader']
    },
    {
      test: /\.html$/,
      loader: 'html'
    }
  ]},
};

```

var entries にオブジェクトでエントリポイントを指定しています。 entriesのkeyに、各コンポーネントフォルダ名(例: component-a) + /(スラッシュ) + "bundle" entriesのvalueに、エントリーポイントのパスを入れています。

entriesのキーを["component-a/bundle"]のように指定してしているのは、webpackがフォルダ構造を考えてよしなにやってくれるからです。 エントリーポイントの指定の仕方は他にもあるので調べてみてください。

- あとは、tsc コマンドと webpack コマンドを実行

```js
tsc -p .

```

```js
webpack
```

これで、build配下に各コンポーネントのディレクトリが作成され、各コンポーネントのディレクトリには、ビルドされたjsファイルとbundle.jsが出力されたかと思います。