Help us understand the problem. What is going on with this article?

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

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

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away