TypeScript+Gulp+Webpack+jQueryで開発環境を構築

# やること
TypeScript, Gulp, WebPack, jQueryを組み合わせて、簡単なWebアプリケーションを作ってみます。

TypeScriptは型が書けたりクラスが書けたりする、AltJS（コンパイルしてjsにして使用する物）です。
TypeScriptはコンパイルしてjsにすることで、ブラウザで使用できるようになります。



今回使う他のツールです。

- Gulp: タスクランナーです。Gruntよりも最近は人気があります。
- Webpack: 各種jsファイルの依存関係を解決し、1つに結合するモジュールバンドラーです。Browserifyなどもこの仲間になります。
- jQuery: 説明不要かと思いますが、楽にDOM操作が出来るライブラリです。

# 開発環境

- Mac OS X High Sierra
- Gulp 3.9.1
- TypeScript 2.9.1
- Webpack 4.10.2
- jQuery 3.3.1


# Node.jsをインストール
必要なモジュールはnpm(Node Package manager)でインストールが出来ます。
まずはNode.jsをインストールします。

`brew install node`

これでnpmが使えるようになります。


# プロジェクトの作成

まずは任意のディレクトリを作成し、その中で以下コマンドを実行してプロジェクトを作成します。
-yオプションをつけないと、各種項目について都度聞かれます。
-yを付けずにそのままEnterを連打してもかまいません。

```bash

$ npm init -y
```
実行すると`package.json`が出来上がります。
後述しますが、このファイルに記載されたライブラリ全てを`npm install`で
インストールできるようになりますので、他の人に配布した際に環境構築が簡単にできます。


# ディレクトリ構成
今回は以下のようなディレクトリ構成を実現します。
TypeScriptファイルはtsディレクトリに置き、コンパイルしたjsはdistに置きます。

```
dist
└── main.js
node_modules
└── typescriptなど
ts
├── index.ts
└── model.ts
gulpfile.js
index.html
package.json
tsconfig.json
webpack.config.js
```

# 各種モジュールのインストール

npmで必要な各種モジュールのインストールをします。

まず、開発時に必要なモジュールをインストールします。

```bash

$ npm install --save-dev typescript webpack webpack-cli webpack-stream ts-loader gulp gulp-stream del jquery @types/jquery
```

`npm WARN deprecated gulp-util@3.0.8:` という文言などが表示されますが、無視して構いません。


これでnode_modulesディレクトリが出来ます。
各モジュールの説明です。

- typescript: TypeScriptです。
- gulp: Gulpです。
- webpack: Webpackです。
- webpack-stream: Gulpにおいて、Webpackを使用するためのものです。
- ts-loader: Webpackにおいて、TypeScriptを使用するためのものです。
- del: ファイルの削除を行うためのものです。
- jquery: jQueryです。


**--save-dev**を付けるとpackage.jsonの`devDependencies`に記載されます。
`npm install`を実行すると、devDependenciesに書かれたライブラリがnode_modulesにインストールされます。
そのためgit管理からはnode_modulesディレクトリは外して問題ありません。


**--save**を付けると`dependencies`に記載されます。


なお、インストールされたモジュールは`npm ls`で確認が可能です。
ただ、依存モジュールも全て表示されてしまいますので、
`npm ls --depth=0`と実行すると依存モジュールが除外され見やすいと思います。

不要なモジュールは`npm remove モジュール名`でアンインストールが出来ます。



# tsconfig.jsonの作成

以下のコマンドで、TypeScriptのコンパイル情報を記載する、tsconfig.jsonを作成します。

```bash

$ npx tsc --init
```


# tsファイルの作成
tsディレクトリを作り、その中にtsファイルを作っていきます。
model.ts, index.ts の2つのファイルを作っていきます。



## model.ts
Modelというネームスペースを使用し、Personクラスをexportしてネームスペースの外から参照できるようにします。

```typescript:model.ts
'use strict';

namespace Model {
    export class Person {
        constructor(private name:string = 'dummy') {
        }

        public getName():string {
            return this.name
        }
    }
}
export default Model;
```

## index.ts

このファイルにメインの挙動を記載します。
`model.ts`とjQueryをインポートして使用します。

```typescript:index.ts

'use strict';
import Model from './model';

// tsconfig.json の esModuleInterop がtrueであれば以下の記述も可能
// import * as $ from 'jquery';
import $ = require('jquery');

let user = new Model.Person("Mike");

$(() => {
    $("#name").html(user.getName());

});
```


# webpack.config.jsの作成

プロジェクトルートに、Webpackの設定ファイルである`webpack.config.js`を作成します。

```javascript:webpack.config.js

'use strict';

module.exports = {
  mode: 'development',
  devtool: 'source-map',
  entry: {
    app :'./ts/index.ts'
  },
  output: {
    path: `${__dirname}/dist`,
    filename: 'main.js'
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        use: {
          loader: 'ts-loader'
        }
      }
    ]
  },
  resolve: { extensions: ['.ts'] }
};

```


# gulpfile.jsの作成
プロジェクトルートに、Gulpの実行ファイルである、gulpfile.jsを作ります。

```javascript:gulpfile.js

'use strict';

const gulp = require('gulp');
const webpackStream = require('webpack-stream');
const webpackConfig = require('./webpack.config.js');
const webpack = require('webpack');
const del = require('del');

const TS_SRC = './ts/**/*.ts';
const JS_DEST = './dist/*';

gulp.task('clean', function() {
  del([JS_DEST]);
});

gulp.task('webpack', function() {
  return webpackStream(webpackConfig, webpack)
    .pipe(gulp.dest("dist"));
});

gulp.task('watch', function () {
  gulp.watch(TS_SRC, ['webpack']);
});

gulp.task('default', ['webpack']);

```

gulpは実行時に引数を与えることが可能で、上記task関数の第一引数に相当します。
`gulp webpack`と実行した場合は、上記の`task('webpack'～`が実行されます。
`gulp`と実行した場合は、defaultと見なされます。

今回は以下のようなタスクを定義しました。

- clean: delを使って、jsファイルを削除します。引数は配列形式で複数のディレクトリの指定が可能です。
- webpack: tsファイルをコンパイルし、distに設置するバッチ処理が起動します。終了されるときはCtrl+Cを押してからYです。
- watch: tsファイルを監視し、変更されたら、時自動的にwebpackコマンドを実行します。
- default: webpackを実行します。

# index.htmlの作成

プロジェクトルートに、ブラウザでアクセスするファイルを作成します。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>TypeScriptのテスト</title>
    <script src="dist/main.js"></script>
</head>
<body>
<div id="name"></div>
</body>
</html>
```


# 動作確認

## Webpackの動作確認

`$ npx webpack`

**dist/main.js** が作成されれば成功です。

## Gulpの動作確認

`$ npx gulp clean`

**dist/main.js** が削除されれば成功です。

`$npx gulp`

**dist/main.js** が作成されれば成功です。


## ブラウザで動作確認
index.htmlを開き、 **Mike** と表示されれば成功です。


# 参考記事
- https://qiita.com/tonkotsuboy_com/items/2d4f3862e6d05dc0bea1
- https://qiita.com/karak/items/29ff148788f5abb15331