babel-loader、eslint-loader、ts-loader比較

webpackを使ってJavascriptとTypescriptのどちらも自由に使える開発環境を作ろう！となったとき、この３つのローダーは機能が重複していたりして「どう使い分けたら…」と悩んだため比較しました。

## 欲しい機能
- .ts、.jsファイルそれぞれlintしてほしい
- TSをJSにコンパイルしてほしい
- ECMAScript5に変換してほしい

## 結論から言うと
**eslint-loader（2020年10月現在非推奨。代替としてeslint-webpack-pluginを推奨）**で
- .jsファイルの静的コード分析

**ts-loader**で
- JavascriptとTypescriptをECMAScript5にコンパイル
- .tsファイルの静的コード分析

以上２つのローダーを使用することにしました。

## ローダーの特徴を比較

### babel-loader
- JavascriptのES2015、ES2016、ES2017、ES2019、ES2020の構文をECMAScript5に変換
- **プリセット「@babel/preset-typescript」によってTypescriptもコンパイル可能**

### eslint-loader（eslint-webpack-plugin）
- Javascriptを静的コード分析

### ts-loader
- TypescriptをECMAScript5に変換
- Typescriptの静的コード分析
- **tsconfigで"allowJs":trueとした場合Javascriptもあわせてコンパイル（ECMAScript5に変換）可能**

導入の際に迷った要素を**太字**にしました。
こう見ると、ts-loaderとbabel-loaderどちらを選んでも機能の差をあまり感じない気がします。（あくまでTSとJSどちらも使用したい、という環境構築が目的の場合）

各設定のコードはこんなかんじ。

```ruby:webpack.config.js
module.exports = {

  module: {
    rules: [
      {
        test: /\.(js|ts)$/, //ts-loaderでは拡張子.js、.tsどちらも監視
        exclude: /node_modules/,
        loader: "ts-loader"
      },
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
      },
  },
  resolve: {
    extensions: [
      '.ts', '.js',
    ],
  },
};

```


```ruby:tsconfig.json
{
  "include": [
    "src/scripts/**/*" //対象にしたいディレクトリを指定
  ],
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Basic Options */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "es2015",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "lib": [
      "es2018",
      "dom"
    ],                             /* Specify library files to be included in the compilation. */
    "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* ここをtrueにするとTypescriptのlintが.jsにもかかるので注意。Report errors in .js files. */
    "sourceMap": true,                     /* Generates corresponding '.map' file. */
    "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */

    /* Source Map Options */
    "inlineSources": true                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
  }
}

```

```ruby:.eslint.json
{
  "extends": ["eslint:recommended"],
  "plugins": [],
  "parserOptions": {
    "sourceType": "module",
    "ecmaVersion": 2015
  },
  "env": {"browser": true},
  "globals": {},
  "rules": {}
}
```

重要なのは```tsconfig.json```の```allowJs: true```と、```webpack.config.js```で```eslint-loader```でjsをlintしてから```ts-loader```が走るような順番で記述することだと思います。
eslintの設定は好みに応じて変更してください。

完成してから思ったのは、babelは開発が活発そう、@babel/preset-typescriptも安心して使えそう、ということでした。。
とはいえ上記組み合わせでも十分求めていた動きをしてくれたので、試しに使ってみてください！

JS初学者が試行錯誤の末行き着いた結果です。色々ご容赦いただければと思います。