Electron用のwebpack configを完全にTypeScriptに移行した

[ElectronアプリをTypeScriptで書くようにした](https://github.com/Maeda-Naoki/TypeElectron)のに、Webpackが`.js`だと、なんかダサいなと思ったので、Webpack関係も[TypeScript](https://www.typescriptlang.org/)に移行した。

Electron用と言いつつ、大抵のプロジェクトで使えると思う。

## 環境
* TypeScript : 3.7.5
* webpack : 4.41.5
* webpack-merge : 4.2.2

## ベース移行
基本的なことは、[公式](https://webpack.js.org/configuration/configuration-languages/#typescript)に書いてある。

### パッケージインストール

```bash
$ yarn add --dev typescript ts-node @types/node @types/webpack
```

### 設定ファイル

```typescript:webpack.config.ts

import * as path from 'path';
import * as webpack from 'webpack';

const config: webpack.Configuration = {
  mode: 'production',
  entry: './foo.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'foo.bundle.js'
  }
};

export default config;
```

`module`を`commonjs`に変更するのをお忘れなく

```json:tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    ...
  }
}
```

## Develop & Production Build設定
`Build mode`を`development`と`production`で分けたかったのでファイルを下記のように分ける。

```bash
・ webpack.common.ts    //共通設定
 ・ webpack.dev.ts      //Prodction Build設定
 ・ webpack.prod.ts     //Development Build設定
```

### Webpack commmon

`mode`は、`webpack.dev.ts`と`webpack.prod.ts`内で設定するから`webpack.common.ts`からは削除

```diff:webpack.common.ts
import * as path from "path";
import { Configuration } from "webpack";

export const main: Configuration = {
- mode: 'production',
  target: "electron-main",
  node: {
    __dirname: false,
    __filename: false
  },
  entry: path.resolve(__dirname, "src", "main", "main.ts"),
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader",
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: [".ts", ".js"]
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js"
  }
};

export const renderer: Configuration = {
- mode: 'production',
  target: "electron-renderer",
  entry: path.resolve(__dirname, "src", "renderer", "renderer.ts"),
  resolve: {
    extensions: [".ts", ".js"]
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "renderer.js"
  }
};
```

### Webpack merge
ここからは、`Webpack.common.ts`に`Configuration`をマージするため[Webpack merge](https://github.com/survivejs/webpack-merge)を使用する。

#### パッケージインストール

```bash
$ yarn add --dev webpack-merge @types/webpack-merge
```

### Webpack production

```diff:webpack.prod.ts
import { Configuration } from "webpack";
import webpackMerge from "webpack-merge";
import { main, renderer } from "./webpack.common";

const prod: Configuration = {
+  mode: "production"
};

const mainConfig = webpackMerge(main, prod);
const rendererConfig = webpackMerge(renderer, prod);

export default [mainConfig, rendererConfig];
```

### Webpack development

```diff:webpack.dev.ts
import { Configuration } from "webpack";
import webpackMerge from "webpack-merge";
import { main, renderer } from "./webpack.common";

const dev: Configuration = {
+  mode: "development",
  devtool: "inline-source-map"
};

const mainConfig = webpackMerge(main, dev);
const rendererConfig = webpackMerge(renderer, dev);

export default [mainConfig, rendererConfig];
```

### npm scripts
最後に`npm scripts`でconfigファイルの呼び出し部分をちょちょいと直せばOK

```diff:package.json
"scripts": {
-    "dev": "webpack --watch --config webpack.dev.js",
+    "dev": "webpack --watch --config webpack.dev.ts",    
-    "build": "webpack --config webpack.prod.js",
+    "build": "webpack --config webpack.prod.ts",
    "start": "electron ./dist/main.js"
  },
```

## 成果物
* [GitHub: TypeElectron](https://github.com/Maeda-Naoki/TypeElectron)

## まとめ
次は、[esbuild](https://github.com/evanw/esbuild)に以降したいな

## 参考サイト
* [Webpack: Configuration Languages TypeScript](https://webpack.js.org/configuration/configuration-languages/#typescript)
* [Qiita: TypeScriptとElectron](https://qiita.com/necomeshi/items/1861ff80e689a377899a)