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を出力
How to
準備に必要なものはインストールされた前提で話を進めます。
- まず、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が出力されたかと思います。
最後に
Angular2で各コンポーネントごとにエントリーポイント作ってビルドしたりするのが正しいのかはよくわからないですが、この記事が同じようなことで詰まってる人の役に立てれば幸いです。