【メモ】Webpack2.x+Gulp4.x+Phaser3+TypeScript+ESLintでの環境設定

# はじめに

最近Web側のことも終えてないのですが、最近仕事でそれっぽい環境構築をすることになったので、残してみます。

## 環境

* Windows7 64bit
* PhpStorm 2019.2.1
* VSCode 1.37.1
* Nodist v0.9.1
* Node.js v10.16.3
* npm v6.9.0
* ESLint v6.2.1
* Prettier v1.18.2
* Phaser3 v3.19.0
* webpack v 4.28.3
* Gulp v4.0.2、Gulp-cli v2.2.0

## Phaser3

利用したゲームフレームワーク。
TypeScriptで作業したかったので、`Phaser 3 Webpack Project Template`を利用。

Phaser 3 Webpack Project Template
https://github.com/photonstorm/phaser3-project-template

## ESLint

はじめはTSLintだったのですが、年内廃止とのことで急遽ESLintへ変更。

* @typescript-eslint/eslint-plugin
* @typescript-eslint/parser
* eslint-config-eslint
* eslint-config-prettier
* eslint-plugin-node
* eslint-plugin-prettier

このあたりを入れて、ESLint+Prettierでフォーマットかけるように設定。
ただ外部ライブラリなど、ESLintがかかってほしくないものは`.eslintignore`に設定して除外。

`.eslintrc.json`は以下のように。基本的には設定を借りる形で最低限の設定。
`@typescript-eslint/camelcase`は一部どうしても例外があるものがあったので、正規表現で該当のものを対象外に設定。

```json
{
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "plugins": [
    "prettier",
    "@typescript-eslint"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "sourceType": "module"
  },
  "rules": {
    "prettier/prettier": ["error", {
      "singleQuote": true,
      "bracketSpacing": true,
      "arrowParens": "always",
      "endOfLine": "lf"
    }],
    "@typescript-eslint/camelcase": ["error", {
      "allow": ["hogehoge"]
    }],
    "@typescript-eslint/class-name-casing": "off",
    "@typescript-eslint/interface-name-prefix": ["error", "always"]
  }
}
```

## webpack

configファイルのベースとなるファイルを用意。
別途開発用、本番用のconfigファイルを用意して、ベースファイルの情報を`webpack-merge`で結合しています。

本番版では作者をコメントとして残したかったので、`webpack.BannerPlugin`を利用。
ただwebpackで`optimization.splitChunks.chunks='all'`の設定をしているので、`node_modules`のファイル…ここではPhaser3のファイルにもコメントが残ってしまいました。

なので`webpack.BannerPlugin`の`exclude`を設定して、分割したファイルを対象外。
また`TerserPlugin`を使っていたので、`teresrOptions.output.comments=/^\**!/`としてBannerPluginのコメントが消えないようにしました。

```js
module.exports = merge(base, {
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          output: {
            comments: /^\**!/
          }
        }
      })
    ]
  },
  plugins: [
    new webpack.BannerPlugin({
      exclude: [/除外するための正規表現/]
    })
  ]
});
```

なお今回プリプロセッサのような仕組みを導入しました。
webpackのLoaderが気になっていたので、、`プリプロセッサ->ts-loader->babel-loader`の順になるように差し込みました。

## Gulp

* Gulpを利用したことがある人が多い
* package.jsonが編集するのは嫌

ということで、タスクはGulp側に書くことに。
基本的にはビルド用のタスクとローカルサーバーを立てるタスク。
ビルド用に関しては、開発・本番と分けています。

そのビルド用のタスクですが、細かいタスクももちろん存在しています。
が、ただ単純に記載してしまうと必要がないのにIDEの項目に出てきてしまいます。
IDE（ここではPhpStormもしくはVSCode）がタスクを表示するのに`--tasks`、`--tasks-json`、`--tasks-simple`のいずれかのオプションをつけているようでした。
なので以下のようなコードで、表示のみするよう対応しました。

```js
let flag = false;

// 引数を整形して取得
const args = minimist(process.argv.slice(2));

// 引数から表示なのか実行なのかを検出する
const keys = Object.keys(args);
for (const optionName of keys) {
  // IDEがリスト表示するのに
  // --tasks, --tasks-json, --tasks-simple
  // の何れかで取得しているようなので、それを検出
  if (optionName.indexOf('tasks') !== -1) {
    flag = true;
    break;
  }
}

if (flag === true) {
  // 空関数で登録して、IDEに表示だけする
  gulp.task('hoge', () => {});
} else {
  // タスクの実処理を記載
  gulp.task('hoge', () => {
    console.log('hoge');
    return Promise.resolve();
  });
}
```

またESLintを入れていたので、webpack実行前にeslintを実行して、エラーだった場合はそこでビルドが失敗するようにしました。

## 終わり

大部分はありものを使いましたが、今流行り（もう廃れそう？ まだ大丈夫？）っぽい環境構築をする機会がなかったので、勉強になりました。