Webpack+babel+ESLintで構築するNode.jsプロジェクト

## はじめに

毎度、Node.jsで何か新しいもの作ろうとするたびに、色んなサイトを調べなおして環境を構築しています。
面倒なので、備忘録も兼ねて記事にしようかと。

フロントエンドで動作するプログラムを作ることを前提とします。

## 動作確認環境
以下の環境で動作確認しています。

* Windows10
	* 64bit
* WSL
	* Ubuntu 18.04 LTS (※WSL上にNode.jsをインストールして開発しています)
* Node.js
	* v11.12.0
* npm
	* 6.9.0
* babel-loader
	* 8.0.5
* webpack
	* 4.29.6
* eslint
	* 5.16.0

## 初期設定

必要なモジュールをインストールします。
事前に `npm init` を行っておくのを忘れずに。

### webpackのインストール
htmlファイル等のコピー及びwatch監視を行いたいので `copy-webpack-plugin` も一緒にインストールします。

```bash
$ npm install --save-dev webpack webpack-cli copy-webpack-plugin
```

### babelのインストール
新しめの構文を使っていきたいのでbabelを使います。
`@babel/polyfill` は `async/await` 使うのに必要だとか何とか。

```bash
$ npm install --save-dev babel-loader @babel/core @babel/polyfill @babel/preset-env
```

### ESLintのインストール
ある程度、構文を厳しくした方が逆に書きやすいと思っています。

```bash
$ npm install --save-dev eslint eslint-loader
```
## 設定ファイル作成

フォルダとファイルの構成は以下を前提とします。

```
ProjRoot
+---dist
|   +---js
|   |   \---[webpackで生成したjsファイルが置かれる]
|   \---[index.htmlのコピー先]
+---src
|   \---[実装するjsファイルを置く場所]
+---.gitignore
+---.eslintrc
+---package.json
+---webpack.config.js
+---index.html
```

この段階では、設定はともかく「実装」を行うのは基本的に `index.html` と `src` フォルダ以下のjsファイルのみのつもりです。

### .gitignore
以下は `Git` での追跡不要。

```bash
node_modules
dist
```

### package.json

スクリプトは以下のようなものを毎度作っています。

```javascript:package.json
 （中略）
    :
"scripts": {
	"watch": "webpack -d --devtool eval-source-map --watch"
},
    :
 （中略）
```

### webpack.config.js

やっていることはjsファイルをひとまとめにすることと `index.html` のコピー。
前は `cpx` 使ってnpmでコピーしていたけど `copy-webpack-plugin` 使うと `watch` で監視してくれるので便利。

```javascript:webpack.config.js
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
	mode: 'development',
	watchOptions: {
		ignored: /node_modules/
	},
	entry: {
		'main': [
			'@babel/polyfill',
			'./src/[作ったjsファイル]'
		]
	},
	output: {
		path: `${__dirname}/dist/js`,
		filename: '[name].js'
	},
	module: {
		rules: [
			{
				enforce: "pre",
				test: /\.js$/,
				exclude: /(node_modules|dist)/,
				loader: "eslint-loader",
				options: {
					fix: true
				}
			},
			{
				test: /\.js$/,
				exclude: /(node_modules|dist)/,
				use: {
					loader: 'babel-loader',
					options: {
						presets: [
							[
								"@babel/preset-env"
							]
						]
					}
				}
			}
		]
	},
	plugins: [
		new CopyPlugin(
			[
				{
					from: './index.html',
					to: '../'
				}
			]
		)
	]
};
```

### .eslintrc

よさそうな設定は調査中。
とりあえず、 `console` の許可とセミコロンの必須化のみ。

```json:.eslintrc
{
	"root": true,
	"extends": "eslint:recommended",
	"rules": {
		"no-console": 0,
		"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
		"quotes": ["error", "single"],
		"semi": ["error", "always"],
		"semi-spacing": ["error", {"after": true, "before": false}],
		"semi-style": ["error", "last"],
		"no-extra-semi": "error",
		"no-unexpected-multiline": "error",
		"no-unreachable": "error"
	},
	"env": {
		"es6": true,
		"browser": true
	},
	"parserOptions": {
		"sourceType": "module",
		"ecmaVersion": 2018
	}
}
```

## おわり
これができればプロジェクトの初期設定は終わりでしょう。
なんか新しいものとかあったら順次更新していきます。

もっといい設定とかESLintのおすすめとかあったら教えてください。


## 参考URL

* [ES2015(ES6)+webpack+babel-loaderで開発環境を構築](https://qiita.com/d-dai/items/23410fa7d84fb1020ea8)
* [eslint で構文チェック (Webpack)](https://qiita.com/oreo3@github/items/8977dce409db6f64e6cf)
* [gulp.distをCopyWebpackPluginで再現する](https://qiita.com/pepoipod/items/e41105e8f3afd47dc01c)
* [セミコロンに関する ESLint ルール](https://qiita.com/mysticatea/items/9da94240f29ea516ae87)