【備忘録：gulp】gulpにTypeScriptをインストール&バンドルまで

gulpでTypeScriptを入れたくて対応してみました。


TypeScriptを使ってみたい！というのと、tsファイルをimportして使いたいが、
webpackを使わずにgulpプラグインでやりたかったのでやってみました。
## 環境
| ツール | バージョン |
|:-:|:-:|
|Mac   |Mojave   |
|node   |v10.15.3   |
|gulp   |4.0.2   |
gulpはインストールされて構築済みの前提で進めていきます。

## TypeScript導入
まずは肝心のTypeScriptのパッケージをインストールしていきます。

```common-lisp:
npm i -D typescript gulp-typescript @babel/preset-typescript
```

## tsconfig.jsonの作成
TypeScriptの静的型チェックなどのオプションを設定するtsconfig.jsonを作成します。

```typescript:tsconfig.json
{
  "compilerOptions": {
    "target": "ES5",
    "module": "ES2015",
    "removeComments": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "alwaysStrict": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "noUnusedLocals": false,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "forceConsistentCasingInFileNames": true,
  },
  "include":[
    "src/**/*"
  ],
  "exclude":[
    "node_modules",
    "dist/**/*"
  ]
}
```
各オプションの説明は公式サイト、
[TSConfig リファレンス紹介](https://www.typescriptlang.org/ja/tsconfig "TSConfig リファレンス紹介")

もしくは以下Qiita記事が分かりやすくおすすめです。
[tsconfig.jsonの全オプションを理解する（随時追加中）](https://qiita.com/ryokkkke/items/390647a7c26933940470 "tsconfig.jsonの全オプションを理解する（随時追加中）")

## gulpfileの修正
次にインストールしたパッケージたちをglpfileに書き込みます。

```javascript:gulpfile.js
// ts
const ts = require('gulp-typescript');
const tsProject = ts.createProject('tsconfig.json'); //先程作成したtsconfig.jsonの読み込み

function typeScript(cb) {
  gulp
    .src(src.ts)//tsファイルがディレクトリを記述してください。
    .pipe(plumber({ errorHandler: notify.onError('typeScript Error:<%= error.message %>') }))
    .pipe(tsProject({}))
    .on('error', function (e) {
      console.log('e:', e);
    })
    .pipe(
      babel({
        presets: ['@babel/preset-env'],
        comments: false,
      })
    )
    .pipe(changed(dist.root))
    .pipe(gulp.dest(dist.js));//tsファイルからコンパイルされた、jsファイルの出力先を記述してください。
  cb();
}
exports.typeScript = typeScript;
```

あとは、gulpのwatchにこのタスクを追加することで、TypeScriptで制作環境が構築できるはずです・

```javascript:gulpfile.js
function watch(cb) {
  gulp.watch(src.ts, gulp.series(typeScript,));
  cb();
}
exports.watch = watch;

exports.default = gulp.series(watch, typeScript);
```

もしくは、以下コマンドを打ってjsファイルにするでも良いかと思います。

```common-lisp:
npx gulp typeScript
```

## 動かなかった場合、、
このままでも動くとは思います。
が、、動かなかった場合.babelrcが必要かと思いますので、そちらの記載もしておきます。

```json:.babelrc
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "ie": 11
        },
        "useBuiltIns": "usage",
        "corejs": 3,
        "modules": false,
        "debug": true
      },
      "@babel/preset-typescript"
    ]
  ]
}
```


## tsファイルをimpoortしてモジュール対応をしたい
今回の本題はここからなんですが、tsファイルで以下のようにimportをやってみました。

```typescript:/src/assets/js/modules/test.ts
export function test(): void {
  window.addEventListener('click', () => {
    const heading1: HTMLElement = <HTMLElement>document.querySelector('h1');
    console.log(heading1);
  });
}
```
/src/assets/js/modules/配下にtest.tsを作り、それをcommon.tsでインポートして、使う感じです。

```typescript:/src/assets/js/common.ts
import { test } from './modules/test';

window.addEventListener('load', (): void => {
  test();
});
```

ただこのやり方だと、import文がrequire文に変換され、ブラウザで動いてくれません。。

## バンドルさせる
調べてみるとバンドルさせる必要があるっぽいので、バンドルをすることにしました。
ただ、webpackの導入はちょっと苦手意識があったので、別の方法でできないかをさらに調べました。

そこで見つけたのが以下２つのパッケージでした。
[browserify](https://www.npmjs.com/package/browserify "browserify")
[through2](https://www.npmjs.com/package/through2 "through2")

browserifyはバンドルツール？だと思うのですが、through2は何をしているかイマイチわかっていないです。。

んで、この２つを組み合わせてgulpfile.jsに、TypeScriptのバンドル処理を記述していきます。

```javascript:gulpfile.js
function bundleTs(cb) {
  setTimeout(() => {
    gulp
      .src(`${dist.js}common.js`)
      .pipe(plumber({ errorHandler: notify.onError('bundleTs Error:<%= error.message %>') }))
      .pipe(
        through2.obj(function (file, encode, callback) {
          browserify(file.path)
            .transform(babelify, { presets: ['@babel/preset-env'] })
            .bundle(function (err, res) {
              file.contents = res;
              callback(null, file);
            });
        })
      )
      .pipe(gulp.dest(dist.js));
    cb();
  }, 500);
}
exports.bundleTs = bundleTs;
```

そして、watch対象に追加します。

```javascript:gulpfile.js
function watch(cb) {
  gulp.watch(src.ts, gulp.series(typeScript,bundleTs));
  cb();
}
exports.watch = watch;
```

これにより無事importしたものをブラウザで反映することができました。

## まとめ
本来であれば、webpackでバンドルした方が簡単で早いのかもしれないのですが、
これはこれで、試行錯誤してできたので達成感がありました。笑。