やりたいこと
- TypeScriptでasync/awaitを使う
- ライブラリの型定義も取得したい
- webpackでビルド
- ついでにgulpタスクとして動かしたい
TypeScript の async/await をいますぐ使う - Qiita でやってる方法のwebpack版。
方針
- awesome-typescript-loaderで一気にできそうだけどやり方がよくわからなかった
- Browserify+tsify+babelifyでもできそうだけどやり方がry)
結局、ts-loaderとbabel-loaderを使った。ES6を経由しつつBabelでES5にする。
ts -> (ts-loader) -> es6 -> (babel-loader) -> es5
必要環境インストール
npmでごっそり取る。
$ npm init
$ npm i -D gulp typescript typings webpack-stream ts-loader babel-loader
$ npm i -D babel-core babel-preset-es2015 babel-preset-stage-0
$ npm i -S babel-polyfill
typingsで型定義取得
tsdが非推奨になったことに注意。typingsを入れる。
$ npm i -g typings
$ typings init
$ typings i lodash -S -A
$ npm i -S lodash
型定義だけ取得するので--save (-S)
と--ambient (-A)
を指定しとけばOK。
そのうちtypingsでライブラリ本体も取れるようになるのかな。
関係ないけどlodashは型定義だけで17000行以上あってビビる。
エントリファイル作成
起点となるスクリプトとしてとりあえずsrc/entry.tsとして書く。
今回はCommonJSライブラリを作成したかったので、exportで外部に出すライブラリを指定している。
import {Foo} from './Foo';
import {Bar} from './Bar';
export = {Foo:Foo, Bar:Bar};
ちなみに三行目をexport = {Foo, Bar};
にしたらライブラリ利用時にReferenceErrorになる。なんでだ。
TypeScriptコンパイル設定
tsconfig.jsonを書く。
{
"compilerOptions": {
"module": "commonjs",
"target": "es6"
},
"files": [
"typings/browser.d.ts",
"src/entry.ts",
"src/Foo.ts",
"src/Bar.ts"
]
}
BabelでES5にするので、TypeScriptのtargetはes6でいい。
typings/(browser|main).d.tsもfilesに追加。
webpackの設定
webpack.config.jsを書く。
追記: ライブラリを作る場合はexternalsを追加しておこう。
module.exports = {
entry: ['babel-polyfill', './src/entry.ts'], // gulp.srcで指定する場合不要
resolve: {
extensions: ['', '.ts', '.js']
},
output: {
path: __dirname + '/lib',
filename: 'bundle.js',
libraryTarget: 'commonjs' // CommonJSとして出力
},
module: {
loaders: [
{
test: /\.ts(x?)$/,
loader: 'babel-loader?presets[]=es2015,presets[]=stage-0!ts-loader'
}
]
},
externals: {
"babel-polyfill": "babel-polyfill",
"lodash": "lodash"
}
};
babelでasync/awaitを使うにはbabel-polyfillの同梱とstage-2以上のpresets指定が必要。
loaderは"!"で繋げる必要がある。この場合query使えないので、presetsはloader記述に埋める。
loaderを単に並べたりpreLoader使うのではbabel-loaderがうまく走らなかった。
ここでだいぶハマった...
追記: さらに結構すっきりさせられる事がわかった。
-
loader
の代わりにloaders
プロパティを使えば"!"の代わりに配列で指定できる - .babelrcを書いておくとbabelが設定を読みにいってくれる
-
babel-loader
の代わりにbabel
と書ける
これらを使えば、
// ...
loaders: [
{
test: /\.ts(x?)$/,
loaders: ['babel', 'ts']
}
]
// ...
{
"presets": ["es2015", "stage-0"]
}
こんなにすっきり!
webpackでビルド
この時点でwebpackを直接叩いてビルドできる。簡単にやるならこれで。
$ npm i -g webpack
$ webpack
gulpでビルド
gulpタスクから叩きたいとき。
var gulp = require('gulp');
var webpack = require('webpack-stream');
gulp.task('webpack', () => {
return gulp.src(['babel-polyfill', './src/entry.ts'])
.pipe(webpack(require('./webpack.config.js')))
.pipe(gulp.dest('lib'));
});
$ gulp webpack
webpack-streamでgulp.src指定するときはwebpack.config.jsのentryは消しておくこと。
残しておいたらファイルサイズでかくなったので、多分どっかでダブってる。
そのまんまwebpack使うなら普通に呼べばOK。
var gulp = require('gulp');
var gutil = require('gulp-util');
var webpack = require('webpack');
gulp.task('webpack', (callback) => {
webpack(require('./webpack.config.js'), (err, stats) => {
if(err) throw new gutil.PluginError('webpack', err);
callback();
});
});
$ npm i -D webpack
$ gulp webpack
以上。いやー疲れた。
いろんな設定をいろんなところに書けるから、何がいい方法かさっぱりわからんね。
もっといい方法あったら教えて下さい。