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の記事で書かれているので、参考にしていただければと思います。
流れ
- gulpfile.jsにタスクを書き込む
- gulp実行で、tsconfig.jsonを出力
- tsc -p . で、tsファイルをjsファイルに変換
- webpack で各コンポーネントのbundle.jsを出力
どうするか
準備に必要なものはインストールされた前提で話を進めます。
- まず、gulpfile.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が出力されます。 出力された内容はこんな感じ。
ファイル名: 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"を指定しています。
オプションの一覧は、この記事とか読んでみると良いかもです。
- webpack.config.jsを編集する
webpack.config.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 コマンドを実行
tsc -p .
webpack
これで、build配下に各コンポーネントのディレクトリが作成され、各コンポーネントのディレクトリには、ビルドされたjsファイルとbundle.jsが出力されたかと思います。