LoginSignup
29
34

More than 5 years have passed since last update.

TypeScriptでasync/await (webpackビルド)

Last updated at Posted at 2016-02-05

やりたいこと

  • 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

以上。いやー疲れた。
いろんな設定をいろんなところに書けるから、何がいい方法かさっぱりわからんね。
もっといい方法あったら教えて下さい。

29
34
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
34