gulp + webpackでTypeScriptをビルドして、ブラウザでデバッグする

##はじめに
TypeScriptのビルド環境を作成する機会があったので、メモとして残します。
構成はgulp+webpack+TypeScript+Sassです。

##筆者の環境
OS X El Capitan
NodeJs v5.8.0
iTerm
VisualStudioCode

##やりたいこと
・TypeScriptのビルド
・Sassのビルド
・開発環境と本番環境の切り分け
・ブラウザ上でTypeScriptをデバッグ


####[TypeScript](http://www.typescriptlang.org)とは
AltJSの一つです。型を持つことにより、コンパイルでエラーを検知したりIDEの予測変換が使えるようになるので、非常に便利です。

####[gulp](http://gulpjs.com)とは
nodejs環境で使用出来るタスクランナーです。TypeScriptのビルドや変更ファイルの監視など、様々なことをタスクとして持たせることができます。

####[webpack](https://webpack.github.io)とは
JavaScriptをモジュールとして結合して、依存関係をなくした一つのjsファイルにすることができます。htmlやcss、画像なども取り込むことができます。


##ディレクトリ構成

```
root┐
    ├── dist
    |   ├── css
    |   └── js   
    ├── src
    |   ├── scss
    |   └── ts
    ├── gulpfile.js
    ├── index.html
    ├── package.json
    ├── tsconfig.json
    └── webpack.config.js
```

##webpackの設定

```webpack.config.js
'use strict'

const path = require('path');
const webpack = require("webpack");
const env = process.env.NODE_ENV;

let config = {
  entry: {
    app :'./src/ts/entrypoint.ts'
  },
  output: {
    filename: 'js/bundle.js'
  },
  resolve: {
    extensions: ['', '.ts', '.webpack.js', '.web.js', '.js']
  },

  module: {
    loaders: [
      { test: /\.ts$/, loader: 'awesome-typescript-loader'}
    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(env)
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
  ]
}

if (env === 'production') {
  // JS圧縮
  config.plugins.push(new webpack.optimize.UglifyJsPlugin({
    compress: {
      warnings: false
    }
  }));
} else {
  // ソースマップ
  config.devtool = 'source-map';
}

module.exports = config;
```
TypeScriptのビルドに、awesome-typescript-loaderを用いてます。
NODE_ENVを取得して、開発環境と本番環境の切り分けを行います。

##tsconfigの設定

```tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": false,
    "removeComments": true,
    "sourceMap": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}
```
sourceMapをtrueにしておきます。
##gulpのタスク作成

```gulpfile.js
// ライブラリの読み込み
const gulp = require('gulp');
const sass = require('gulp-sass');
const cssMin = require('gulp-clean-css');
const plumber = require('gulp-plumber');
const runSequence = require('run-sequence');
const del = require('del');
const webserver  = require('gulp-webserver');
const webpack = require('gulp-webpack');
const webpackConfig = require('./webpack.config.js');
const env = process.env.NODE_ENV;

// jsとcssの削除
gulp.task('clean', () => {
  del(['./dist/js/**', './dist/css/**']);
});

// TypeScriptのコンパイルとwebpackの実行
gulp.task('webpack', () => {
  gulp.src(['./src/ts/*.ts'])
  .pipe(plumber())
  .pipe(webpack(webpackConfig))
  .pipe(gulp.dest('./dist'));
});

// 簡易サーバーを立ち上げる
gulp.task('serve', () => {
  gulp.src('./')
    .pipe(webserver({
      host: 'localhost',
      port: 8000,
      livereload: true,
      open: true
    }));
});

// sassのコンパイル
gulp.task('sass', () => {
  gulp.src('./src/scss/*.scss')
    .pipe(plumber())
    .pipe(sass())
    .pipe(gulp.dest('./dist/css'));
});

// css圧縮
gulp.task('cssMin', () => {
  gulp.src('./dist/css/*.css')
    .pipe(plumber())
    .pipe(cssMin())
    .pipe(gulp.dest('./dist/css'));
});

// tsとsassの監視
gulp.task('watch', () => {
  gulp.watch('./src/**/*.ts', ['webpack']);
  gulp.watch('./src/scss/*.scss', ['sass']);
});

// デフォルトタスク
gulp.task('default', () => {
  if (env === 'production') {
    runSequence('clean', ['webpack', 'sass'], 'cssMin');
  } else {
    runSequence('clean', ['webpack', 'sass'], 'watch', 'serve');
  }
});

```
デフォルトタスクで、開発環境と本番環境の切り分けを行っています。

##実行してみる

```起動コマンド
gulp
```

![debug.png](https://qiita-image-store.s3.amazonaws.com/0/60362/2cf6ca25-eb72-00f8-cf26-e6c1d33f0564.png)
TypeScriptファイルでデバッグできていることが確認できます。


##改善点したい部分
・簡易サーバー部分の見直し
・tsconfigとwebpackの見直し（設定がちょっと怪しい気がする）
・テストとかESLintを導入したい

##おわりに
ソースコードは[github](https://github.com/shingokanase/typescript-build-sample)においてあります。
試したい方や、遊びたい方はぜひ触ってみてください。

##参考記事
- [Gulp+WebPackで作るTypeScript開発環境【5分でできる！】](http://liginc.co.jp/201842)
- [2016年から始めるTypescript](http://qiita.com/rglay/items/4b7c7e4b8fd0bca05055)