Node.jsでimport・export（ES6の構文）を使えるようにwebpack × Babelの設定をする

https://note.com/shift_tech/n/n77562e0926e3

※上記の記事では`@babel/preset-env`のオプションで[`targets`](https://babeljs.io/docs/en/babel-preset-env#targets)を指定していない。そのためES5にトランスパイル（変換）しようとするので、core-jsとregenerator-runtimeが必要だが、Nodeに限って言えばES5にせずともモジュールシステムをimportからrequireに変換すればES6以降の構文はほぼ使える（使えないものがあるのかは調べられていない）のでcore-jsとregenerator-runtimeは不要だろう。もはやIEもサポート切れになるので、ES5にまでJavascriptのversionを下げる必要性は少なくなってきていると思われる。

## 補足
### 設定全体は以下を参照

https://github.com/yuta-katayama-23/node-express/tree/d3224ed684d0a96894fd112b049d4ca8db9ef776

※babelの設定で、`targets: { node: 'current' }`という記述を見かける事があると思うが、これは[targets.node](https://babeljs.io/docs/en/options#targetsnode)に書かれている通り、実行環境のNode.jsのversionで動くjavascriptにトランスパイル（変換）するという設定で、`process.versions.node`と書くのと同じ意味になる（以下、公式からの引用）。

> If you want to compile against the current node version, you can specify "node": true or "node": "current", which would be the same as "node": process.versions.node.（現在のノード・バージョンに対してコンパイルしたい場合は、"node": true または "node" を指定します。"current "を指定すると、"node": process.versions.node と同じになります）

```js
module.exports = {
	presets: [
		[
			'@babel/preset-env',
			{
				...,
				targets: { node: 'current' }
			}
		]
	],
};
```

### おまけ
今回、Node.jsでimport・export（ES6の構文）を使えるようにする方法を見てきたが、上記のように`import 'core-js/stable';`, `import 'regenerator-runtime/runtime';`と書かないでも動く場合もあり混乱した。ちょっとどのパターンならbuildして動くのか？を調査してみたので以下にまとめてみた。

**※注意<br>　今回検証に使ったコードだから動いただけの可能性もあり、この辺りはまだ理解が完全ではないため参考情報程度に見て頂ければと思います**

※buildは`npx webpack --mode=development`の事で、server起動は`node dist/main.js`の事

| # | パターン概要 | build・server起動結果 |package.json | .babelrc(babel.config.js) | index.js |
|:-:|---|---|:-:|:-:|:-:|
| 1 | webpackの設定のためのライブラリのみ | ・build：成功<br>・server起動：エラー<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/adccd304-89af-a54d-f9c9-88b3620a5561.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/e38930c6-b154-7cab-c3e0-219d68bad1d4.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/09fae6d5-341b-8ddd-e2f9-653ba6cd8e3c.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/636acf42-1079-3570-b8d5-d2374a338714.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/304dc6b3-21d0-99bf-4e18-78cf8ae4fde3.png) |
| 2 | core-jsとregenerator-runtimeを依存に追加のみ<br>`npm install -D core-js regenerator-runtime` | ・build：成功<br>・server起動：エラー<br>（上と同じ） | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/af2443ae-1022-9a24-c0e4-143884e2c6fd.png) | （上と同じ） | （上と同じ） |
| 3 | babelの設定に[useBuiltIns](https://babeljs.io/docs/en/babel-preset-env#usebuiltins)を追加（`usage`）<br>※必要なpolyfillだけ読み込むように設定 | ・build：成功<br>・server起動：成功<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/919bba2a-d543-9e7e-9fec-d6b4726becf2.png) | （上と同じ） | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/0c98b53c-6ed6-7644-c3dd-a8fa2775b8c9.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/a43d3d94-f6b1-5013-7813-e61e60b40f61.png) | （上と同じ） |
| 4 | babelの設定に[useBuiltIns](https://babeljs.io/docs/en/babel-preset-env#usebuiltins)を追加（`entry`）<br>※全polyfillを読み込む | ・build：成功<br>・server起動：エラー<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/adccd304-89af-a54d-f9c9-88b3620a5561.png) | （上と同じ） | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/875150a8-7479-dabd-cb21-19b52cb288e8.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/71b4757f-6fa7-7fb5-1985-c31f9b794424.png) | （上と同じ）|
| 5 | index.jsに`import 'core-js/stable';`, `import 'regenerator-runtime/runtime';`を追記 | ・build：成功<br>・server起動：成功<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/919bba2a-d543-9e7e-9fec-d6b4726becf2.png) | （上と同じ） | （上と同じ） | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/734b5998-4f96-c11d-e311-a05e794a5f6a.png) |

※5のパターンは、上記の[結論どうすればいいか](#結論どうすればいいか)の設定に加えてbabelのconfigurationの設定も追加したものになる。

※やってみて分かったが、パターン5のようにindex.jsに`import 'core-js/stable';`, `import 'regenerator-runtime/runtime';`を書いた状態ではファイルサイズが大きくなるので、パターン3のようにuseBuiltInsの設定を`usage`にしてindex.jsでのimportはなしのやり方がいいかもしれないが、今までの`@babel/polyfill`では全てのpolyfillを読み込んでいたので、素直にimportの書き方だけ（[結論どうすればいいか](#結論どうすればいいか)の設定）をするでもいい気もする

| パターン | main.jsのファイルサイズ |
|:-:|:-:|
| 3 | 1.11 MiB ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/d61c52e2-0c29-8bbb-839d-22ee36c98c2d.png) |
| 5（[結論どうすればいいか](#結論どうすればいいか)のやり方） | 1.72 MiB<br> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/acd0b6b2-ad2c-e6a2-fd9e-fa6d6293f2cd.png) |

※ちなみ、非推奨になった`@babel/polyfill`を使ってbuildをすると、サイズは`1.42 MiB`だった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/45951440-36de-f812-dc2f-c290f8a66d98.png)

```js:webpack.config.js
module.exports = {
  target: 'node',
  entry: ["@babel/polyfill", "./app/js"],
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
    ],
  },
};
```