webpackについて学んでみた

普段はバックエンドをメインに、PHP/Laravelでアプリケーション開発を行っています。

今回、新規にページ作成にあたり、弊社で以前から利用しているwebpackを学んでみました。
（今まではなんとなくで使っていました）

## webpackとは

複数のJavascript, CSS, assets等の依存関係を考慮して
適切に1つ以上のファイルにバンドルしてくれるシステムです。

### 例
以下のように依存関係にある2つのJavascriptがあるとします。

```javascript:src/index.js
import bar from './bar.js';
bar();
```

```javascript:src/bar.js
export default function bar() {
  //
}
```

通常はそれぞれを読み込む必要があります。
```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    ...
  </head>
  <body>
    ...
    <script src="src/bar.js"></script>
    <script src="src/index.js"></script>
  </body>
</html>
```

しかし、 `webpack` を利用してバンドルすることで

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    ...
  </head>
  <body>
    ...
    <script src="dist/bundle.js"></script>
  </body>
</html>
```

こうなります！

複数のファイルをバンドルし、結果としてフロント側から呼び出すファイルの数が減るため
リクエスト負荷の削減が期待されます。

## 標準的な導入方法

[公式ドキュメント](https://webpack.js.org/guides/getting-started/)を元に実際にセットアップしてみます。
はじめにwebpackをインストールするディレクトリを用意し、`npm`の初期化を行い下記パッケージをインストールします。

- webpack
- webpack-cli

`webpack-cli`は`webpack`をコマンドラインから実行するために必要なパッケージです。

```shell
mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
```

webpackのインストールは以上で終了です！

プロジェクトを誤って公開することがないように`package.json`の`main`を削除して`"private":true`に変更します。
package.jsonの詳細については[公式ドキュメント](https://docs.npmjs.com/files/package.json)を参照してください。

```json:package.json
{
  "name": "webpack-demo",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "devDependencies": {
    "webpack": "^5.77.0",
    "webpack-cli": "^5.0.1"
  }
}
```

## webpackの動作をカスタマイズする

`v4.0.0`以降、webpackでは特別な設定ファイルを必要はしていません。
しかし、多くのプロジェクトでは様々な要求に応じるためカスタマイズを必要とします。

webpackでは`webpack.config.js`というファイルを用意することで
動作をカスタマイズできるようになっています。

設定ファイルを用意しない場合は、プロジェクトのエントリポイントが`src/index.js`であると想定し、
本番用に縮小および最適化された`dist/main.js`に結果を出力します。

設定できるオプションは膨大に存在しており、全てを一から設定するのは大変です。
そのため、webpackではプロジェクト初期化のコマンドが用意されています。

```shell
npx webpack init
```

上記のコマンドを実行しました。
各設定に関する質問が表示されYes/Noで回答するだけでプロジェクトの設定が完了しました！

```shell
% npx webpack init
[webpack-cli] For using this command you need to install: '@webpack-cli/generators' package.
[webpack-cli] Would you like to install '@webpack-cli/generators' package? (That will run 'npm install -D @webpack-cli/generators') (Y/n) Y
npm WARN deprecated readdir-scoped-modules@1.1.0: This functionality has been moved to @npmcli/fs
npm WARN deprecated @npmcli/move-file@1.1.2: This functionality has been moved to @npmcli/fs
npm WARN deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs

added 371 packages, and audited 489 packages in 14s

63 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
? Which of the following JS solutions do you want to use? ES6
? Do you want to use webpack-dev-server? Yes
? Do you want to simplify the creation of HTML files for your bundle? No
? Do you want to add PWA support? No
? Which of the following CSS solutions do you want to use? SASS
? Will you be using CSS styles along with SASS in your project? Yes
? Will you be using PostCSS in your project? Yes
? Do you want to extract CSS for every file? Yes
? Do you like to install prettier to format generated configuration? Yes
? Pick a package manager: npm
[webpack-cli] ℹ INFO  Initialising project...
 conflict package.json
? Overwrite package.json? overwrite
    force package.json
   create src/index.js
   create README.md
   create index.html
   create webpack.config.js
   create .babelrc
   create postcss.config.js

Changes to package.json were detected.

Running npm install for you to install the required dependencies.

up to date, audited 489 packages in 1s

63 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm WARN config cache-min This option has been deprecated in favor of `--prefer-offline`.

added 325 packages, and audited 814 packages in 4s

92 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
[webpack-cli] Project has been initialised with webpack!
% 
```

生成された設定ファイルは下記のようなものになります。

```javascript:webpack.config.js
// Generated using webpack-cli https://github.com/webpack/webpack-cli

const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const isProduction = process.env.NODE_ENV == "production";

const stylesHandler = MiniCssExtractPlugin.loader;

const config = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
  },
  devServer: {
    open: true,
    host: "localhost",
  },
  plugins: [
    new MiniCssExtractPlugin(),

    // Add your plugins here
    // Learn more about plugins from https://webpack.js.org/configuration/plugins/
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/i,
        loader: "babel-loader",
      },
      {
        test: /\.s[ac]ss$/i,
        use: [stylesHandler, "css-loader", "postcss-loader", "sass-loader"],
      },
      {
        test: /\.css$/i,
        use: [stylesHandler, "css-loader", "postcss-loader"],
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
        type: "asset",
      },

      // Add your rules for custom modules here
      // Learn more about loaders from https://webpack.js.org/loaders/
    ],
  },
};

module.exports = () => {
  if (isProduction) {
    config.mode = "production";
  } else {
    config.mode = "development";
  }
  return config;
};
```

弊社では、上記以外の設定も加えて運用しています。

初期設定外にどのようなオプション設定ができるのかは
適宜、[公式ドキュメント](https://webpack.js.org/)を参考に設定してみてください！

以上、webpackについてインストール〜初期設定について学んでみた結果でした！

多種多様に柔軟な設定が可能、かつ様々なプラグインなどを利用できるので
私と同様に初心者の方は是非とも、どんな活用ができるのか試してみていただければと思います。

---

## おまけ

仕事でVueを触っていて「おもしれぇぇぇぇぇえぇえええええ」って思ったので
プライベートでも[公式ページ](https://ja.vuejs.org/)を見ながら環境を構築してみました。

Vueは[Vite](https://ja.vitejs.dev/)（ヴィートって読むんですって）を推奨しているようで
Vue+Viteの環境が…たった数秒で構築できてしまった！！！！

しかも動作が速い！ものすごく速い！

これから始めるならViteの方がオススメかもしれません…