【初心者向け】webpackの基本構成を紹介(devserverの導入も)

webpackの環境構築をよくやるので、共有と備忘録を兼ねて、初心者の方向けにwebpackの導入を書いてみました。

単にwebpackをインストールするだけでなく、基本的な設定やwebpack-dev-server(定番の開発用サーバー)の導入も合わせてやっていきます。


## ▼前提条件
- **PCにnode.jsがインストールされていること（重要）**
- **cdコマンドなど、基本的なターミナル操作ができること（重要）**
- webpackがどんなものかはなんとなく知っている
- JSモジュールの概念はふわっと程度に知っている

前提条件が初心者向けじゃないかもしれない。
webpackがまったく分からんという人は、このあたりを読んでみるのいいかも。

https://ics.media/entry/12140/

https://webpack.js.org/

## ▼私の環境

- OS : Win10 home
- Editor : VScode
- Terminal : bash
- Node.js version : v14.16.1

macOSの人でも手順自体は一緒だと思います（エアプ）あと、npm使ってます。


## ▼本編
**やること：webpackの初期導入。ビルド確認と、開発用サーバーの立ち上げ。**

### ▽1.作業用ディレクトリを作成
作成するプロジェクト用に、空のディレクトリを作りましょう。
僕は今回、「webpack-test」という名前の空ディレクトリを作成することにします。


▼ディレクトリを作ったらターミナルを開いて

```terminal:terminal(bash)
//作成したディレクトリの中に移動。
$ cd webpack-test //さっき作ったディレクトリの名前

//package.jsonを作成
$ npm init -y
```

ディレクトリ内に"package.json"が生成されたら成功！

### ▽2.webpackをインストール
▼webpack本体とCLIだけでもいいのですが、
今回はwebpack用の便利なローカルサーバー、"webpack-dev-server"もインストールします。後で使い方も解説します。

```terminal:terminal(bash)
npm i -D webpack webpack-cli webpack-dev-server
```
少し時間がかかるので、しばし待ちましょう。

### ▽3.記述をまとめるディレクトリを作成
▼続いて、記述するファイルをまとめておく為のディレクトリを作成します。一般的に"src"とされることが多い為、ここでもそのようにします。
srcの中に、テスト用のJSファイルを追加しておきましょう。

```diff:ここまでのディレクトリ構成
root(私の場合はwebpack-test)
 ├── node_modules
+├── src
+│    ├──index.js //バンドル用
+│    └──app.js //処理の記述用
 ├──package-lock.json
 └──package.json
```


▼app.jsには簡単なサンプルコードを記述しています。console.log("hello world")とかでもいいのですが、今回はHTMLファイルに文字を出力したかったので以下のようにしました。目的はあくまで動作確認なので、自分が分かれば何でもいいです。ちなみに今回は動作確認なのでapp.jsだけですが、実際はもっとたくさんのファイルを作る場合がほとんどです。

```javascript:app.js
export function fn() {
  //htmlファイルは後から作るよ
  const sampleText = document.querySelector("#content");
  sampleText.insertAdjacentHTML('beforebegin', '<p>とんかつ食いたい</p>');
}
```

▼そして、app.jsでエクスポートしたfn関数を、まとめ（バンドル）役であるindex.jsへインポートし実行します。index.js自体に処理を直接書くことは基本的にはなくて、こいつはあくまでたくさんあるJSファイルをまとめて出力するための存在です。

```javascript:index.js
//index.js内にapp.jsで作ったfn関数をインポート
import { fn } from "./app";
//実行
fn();
```
▼ここで一度、ビルドが通るかどうかテストしておきましょう。

```terminal:terminal(bash)
$ npx webpack　

//注意：npmではなく、npxだゾ。
```
"npx webpack"でビルドが走ります。"dist"というフォルダがルート直下に生成され、その中に"main.js"があればとりあえずOK。"main.js"を見てみると、先ほど記述した"src"の中身が吐き出されています。

ビルド時、ターミナルにwarningと表示されてもとりあえず無視でおｋ。^^b

###▽4.HTMLを追加しとく
今回はブラウザに文字を出力してビルドがきちんと行えているか確認したいので、HTMLファイルも追加したいと思います。
今回は、さっき生成された"dist"フォルダの中にindex.htmlを追加しましょう。

▼前回のディレクトリ構成との差分はこんな感じになると思います。

```diff:distの中にindex.htmlを追加
root
+├── dist //←npx buildで勝手に生成された
+│    ├──index.html
+│    └──main.js
 ├── node_modules
 ├── src
 │    ├──index.js
 │    └──app.js
 ├──package-lock.json
 └──package.json
```

▼作成したhtmlファイルの中身を記述します。VScodeのユーザーは、「!」を出力した後tabキー押しでHTMLの骨組み部分が一気に作れるので試してみてください。
それから、bodyタグの直前でmain.jsを読み込んでおくのを忘れずに。

追記：ショートカットがうまくいかない人は、「VSCode Emmet」とかでググってみてください。。覚えておいて損はないので。



```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack test(好きなタイトルを入れる)</title>
</head>
<body>
  <p>お前と一緒に</p>
  <div id="content"></div>　<!-- fn関数で使っているID要素 -->
  <script src="main.js"></script>　<!-- ←これ忘れんなよ～～～～ -->
</body>
</html>

```

###▽5.webpack.config.jsを作成。
まだやることがあります（笑）webpackの細かい設定を書き込むためのファイル、webpack.config.jsを作ります。
別にこのファイルが無くてもwebpackは動く（さっきビルドできたし）のですが、実践でこれを書かないということはほぼないんじゃないかなあ。

そういうわけで「webpack.config.js」これをルート直下に新規作成します。
▼画像参照

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1672759/fe4c4069-f697-b669-aced-eb1dde348056.png)

今回webpack.config.jsでやることは、

- モード指定（開発モードor本番モード）
- エントリーファイル（出力元）のファイルを指定
- 出力先のディレクトリを指定
- 出力をまとめるjsファイルを指定
- webpack-dev-serverの設定を記述

上記5点を設定します。あまり話すと長くなるので、実際の記述をご覧ください。コピペしてもらって大丈夫です。

```javascript:webpack.config.js
const path = require('path');
module.exports = {
  
  //モード指定。開発モードである"development"を選択。本番モードは"production"だった気がする
  mode: "development",
  //entry(出力元)のファイルを指定。
  entry: './src/index.js',
  //output(出力先)
	output: {
    //出力されるディレクトリのパスとディレクトリ名を指定。デフォルトの"dist"のままにしてる
		path: path.resolve(__dirname, 'dist'),
    //生成されるJSファイル名を指定。ここもデフォルトのまま。
		filename: 'main.js'
	},
  
  //webpack-dev-serverのオプション
  devServer: {
    //サーバーで立ち上げるディレクトリを指定
    static: {
      directory: path.join(__dirname, 'dist'),
    },

    //open:trueでサーバーを起動したときに自動的にブラウザを立ち上げる
    open: true
  }
};
```

こんな風に書きます。**ちなみにwebpack-dev-serverのオプションであるdevServerの項目ですが、バージョンによって書き方が異なるので注意してください。(2021/09/05)**
webpackのプラグインは、アップデートで記述方法が変わってしまうことが良くあるので、公式ドキュメントを参照しながら作業することをお勧めします。ドキュメントはブックマークしちゃいましょう。


https://webpack.js.org/configuration/dev-server/


###▽6.コマンドをカスタマイズ
ビルドとwebpack-dev-serverの立ち上げをひとつのコマンドで実行出来たら便利！ということで、package.jsonを少し変更します。注目して頂きたいのは"scripts"の中身です。"scripts"部分の既存の記述を消して、以下のように書き直してみてください。（そのほかの部分はそのままでOK）


```diff:package.json
{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
+  "scripts": {
+    "dev": "npx webpack && webpack-dev-server",　←ここでビルド＆サーバー立ち上げを指定してる
+  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.51.2",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.1.0"
  }
}

```

npm run dev とコマンドを打てば、ビルドとdevserverの立ち上げを同時に行うことが可能となっています。今回は"dev"（開発用,developmentの意）という名前を付けましたが、この部分は任意の名前でOKです。

###▽7.ビルド＆サーバーの立ち上げを確認（さいご）
最後に、ビルド＆devserverの立ち上げを実際に行い、上手くいっているかどうか確認してみましょう。

```terminal:terminal(bash)
$ npm run dev
```
ビルドの実行とともにdevServerも起動、自動でブラウザの画面に遷移するはずです。app.jsで記述した、「とんかつ食いたい」も無事出力されていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1672759/96a39527-9cca-dde4-d79f-cede229db3bb.png)

これで、HTMLとJSを使った開発はとりあえずできそうです。

## ▼余談：エラーが出てきた時の対処
環境構築系はたいていどっかで沼るんですよね。
webpackでもビルドエラーが起きて詰むことがよくあるのですが、ほとんどの場合エラーコードが原因をちゃんと教えてくれます。僕はエラーコードを翻訳ツールにコピペしたり、ググってみたり、、、と色々とやりながら解決の糸口を見つけて何とか乗り越えています。

まあ練習なので、焦ってもしょうがないんですけどね～。一回もハマらずに環境構築出来たら奇跡ぐらいに思って、気長にやりましょう。

##▼最後に

実践ではここからCSSや画像のバンドル、BabelやESLintの導入など、プロジェクトに応じた設定を行っていくことになります。webpackは面倒ですが、あれこれ増築して開発が効率的になってくるのが分かるとなるとちょっとだけ楽しいです。

間違っている部分や、おかしな記述があればぜひ教えてほしいです。改善・解決します。
次回はwebpackでReactを使うための環境構築について書こうと思っています。出来上がり次第こちらの記事にもリンクを貼っておきます！
ほなまた！