Edited at

TypeScriptでasync/await (webpackビルド)

More than 3 years have passed since last update.


やりたいこと


  • TypeScriptでasync/awaitを使う

  • ライブラリの型定義も取得したい

  • webpackでビルド

  • ついでにgulpタスクとして動かしたい

TypeScript の async/await をいますぐ使う - Qiita でやってる方法のwebpack版。


方針



  • awesome-typescript-loaderで一気にできそうだけどやり方がよくわからなかった

  • Browserify+tsify+babelifyでもできそうだけどやり方がry)

結局、ts-loaderbabel-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で外部に出すライブラリを指定している。


src/entry.ts

import {Foo} from './Foo';

import {Bar} from './Bar';
export = {Foo:Foo, Bar:Bar};

ちなみに三行目をexport = {Foo, Bar};にしたらライブラリ利用時にReferenceErrorになる。なんでだ。


TypeScriptコンパイル設定

tsconfig.jsonを書く。


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を追加しておこう。


webpack.config.js

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と書ける

これらを使えば、


webpack.config.js(一部)

  // ...

loaders: [
{
test: /\.ts(x?)$/,
loaders: ['babel', 'ts']
}
]
// ...


.babelrc

{

"presets": ["es2015", "stage-0"]
}

こんなにすっきり!


webpackでビルド

この時点でwebpackを直接叩いてビルドできる。簡単にやるならこれで。

$ npm i -g webpack

$ webpack


gulpでビルド

gulpタスクから叩きたいとき。


gulpfile.js

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。


gulpfile.js

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

以上。いやー疲れた。

いろんな設定をいろんなところに書けるから、何がいい方法かさっぱりわからんね。

もっといい方法あったら教えて下さい。