Webpackの基本的な使い方まとめ

Webpack についてまとめました。

この記事は以下の構成になっています。

  • Webpack とは
  • Webpack のインストール
  • webpack.config.js
  • バンドル
  • モード
  • ローカルサーバー
  • ソースマップ
  • Babel の設定
  • CSS の設定

Webpack とは

Webpack は、JavaScript におけるモジュールバンドラであり、複数の静的なリソース(JavaScriptCSS、画像など)をバンドルし、バンドルされたファイルを最適化するツール。

バンドルとはファイルを 1 つにまとめること。

Webpack を使う主な目的は、クライアントサイドでのウェブ開発において、複雑な依存関係を持つ複数のファイルを一つまたは少数のファイルにまとめ、最適化すること。

Webpack のインストール

Webpack をインストールするには Node.js がインストールされていることが前提。

Webpack は npm でwebpackwebpack-cliのパッケージをインストールして使う。

npm i -D webpack webpack-cli

webpackは Webpack 本体で、webpack-cliは Webpack を CLI から使うために必要。

Webpack は開発環境で使うものなので、-Dをつける。

webpack.config.js

Webpack の設定はプロジェクトの直下にwebpack.config.jsを作成して行う。

webpack.config.jsは以下のように CommonJS 形式で記述する。

module.exports = {};

{}の中で設定をオブジェクトのプロパティとして記述していく。

module.exportsはオブジェクトを外部から使えるようにするためにエクスポートして、Webpack が設定に基づいてビルドを制御する。

簡単に言えば、設定を記述したオブジェクトをエクスポートして Webpack が読み込めるようにしている。

バンドル

1. 設定

バンドルの設定はデフォルトでは、エントリーポイントであるsrc/index.jsを読み込んで、dist/main.jsで出力する。

そのため JavaScript をモジュールで分割しても、最終的にはsrc/index.jsで読み込んでいる必要がある。


エントリーポイントや出力先を変更したい場合はwebpack.config.jsに設定を記述する。

const path = require('path');

module.exports = {
  // エントリーポイント
  entry: './resources/app.js',

  // 出力先
  output: {
    path: path.resolve(__dirname, 'public'),

    // 出力ファイル名
    filename: 'bundle.js',
  },
};

2. 実行

バンドルを実行するにはnpx webpackを実行する。

バンドルが成功するとデフォルトではdist/main.jsが作られ、すべての JavaScript のコードが書かれている。


オプションとして--watchをつけて実行すると、変更が監視され自動で反映される。

webpack.config.jsでも設定できる。

module.exports = {
  watch: true
};


また実行コマンドはpackage.jsonscriptsに登録できる。

{
  "scripts": {
    "dev": "webpack",
  }
}

モード

Webpack はproductiondevelopmentnoneの 3 つのモードでビルドできる。

productionコードを圧縮してビルドする本番環境用のモード。

developmentは、開発時のモードで、ソースマップを有効にする。

noneproductiondevelopmentの設定が適用されず、すべての最適化機能が無効になるモード。

コマンドで実行する場合は、以下のようにする。

# デフォルトではproduction
npx webpack

# development
npx webpack --mode development


webpack.config.jsでも設定できる。

module.exports = {
  mode: 'development'
};


ちなみに圧縮を行うかどうかはoptimizationminimizeで設定できる。

productionモードの場合はデフォルトでminimizetrueになっているので自動で圧縮される。

以下のようにfalseにすると圧縮を行わない。

module.exports = {
  optimization: {
    minimize: false
  }
};

ローカルサーバー

Webpack ではファイルの変更を検知して自動でビルドするローカルサーバーを構築できる。

ローカルサーバーを使えば、ビルドコマンドを手動で実行する必要がなくなる。

1. インストール

ローカルサーバーを使うにはwebpack-dev-serverのパッケージが必要。

npm i -D webpack-dev-server

2. 設定

webpack.config.jsに以下の設定を記述する。

module.exports = {
  devServer: {
    static: "dist",

    // 自動でブラウザを起動する
    open: true
  }
};

3. 実行

package.jsonscriptsに以下のコマンドを記述する。

{
  "scripts": {
    "start": "webpack serve"
  },
}

これでnpm run startを実行するとローカルサーバーを起動できる。

ソースマップ

ソースマップはバンドルしたコードを元のコードに対応づけるためのマッピングファイル。ソースマップを生成すると、ブラウザの開発ツールでコードを確認できるようになる。

1. 設定

ソースマップを生成するにはwebpack.config.jsに以下の記述を行う。

module.exports = {
  devtool: 'source-map'
}

2. 実行

ソースマップを設定している状態でバンドルを実行すると、拡張子が.mapというファイルが出力される。

デフォルトのmain.jsを出力する場合だと、同じディレクトリ内にmain.js.mapが出力される。

Babel

Babel は JavaScript の新しいの記法を古いブラウザでも対応できるように ES5 の記法に変換(トランスパイル)するツール。

ES6 から ES5 への変換だけでなく、JSX や TypeScript のトランスパイルも行うことができる。

Babel は単体だと手動で実行しなければならないため、Webpack に導入することでバンドルと同時にトランスパイルを実行できる。

Webpack で Babel が使われる流れ 1. は以下のようになる。

  1. Webpack がエントリーポイントからすべてのファイルを解析する
  2. .jsファイルを検出したらbabel-loaderが適用される
  3. 設定した presets でトランスパイルを行う
  4. トランスパイルされたファイルを Webpack がバンドルする

設定例:ES6→ES5

1. インストール

Babel を導入するには Babel 本体である@babel/coreと、ES6 から ES5 に変換するための@babel/preset-envと、Webpack で Babel を使うためのbabel-loaderをインストールする必要がある。

npm i -D @babel/core @babel/preset-env babel-loader

presetは一連のプラグインをまとめたもので、@babel/preset-env以外にも、JSX を JavaScript に変換する@babel/preset-reactや、TypeScript を JavaScript に変換する@babel/preset-typescriptなどもある。

loaderは JSX や TypeScript、JavaScript 以外の CSS や画像を JavaScript に変換するプログラム。

2. 設定

webpack.config.jsに以下の内容を記述して、babel-loaderを使うように設定する。

module.exports = {
  module: {
    rules: [
      {
        // 拡張子がjsのファイルを対象
        test: /\.js$/,

        use: {
          // ローダーを指定
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"]
          }
        }
      },
    ],
  },
};

moduleは Webpack がモジュール(JavaScript ファイルやその他のファイル)を解析し、変換する際のルールを定義するための設定。

rulesは特定のファイルタイプに対する処理方法を指定する。

test正規表現を使って、設定を適用するファイルを指定する。

useはオブジェクトで指定することでローダーとオプションを設定している。

loaderは単一のローダーを指定する。複数のローダーを使うときはuseを配列で指定する。

optionsはローダーに渡すオプションを指定するもので、presets@babel/preset-envを使うようにしている。


また、プロジェクト直下に.babelrcまたはbabel.config.jsonを作成して設定を行う方法もある。

以下の記述で、ES6 から ES5 に変換するように設定する。

{
  "presets": ["@babel/preset-env"]
}

設定例:JSX

React で使う JSX も Babel でトランスパイルできる。

1. React の準備

JSX を使うので、React が必要。

npm i react react-dom


次にディレクトリ構成を以下のようにする。

├── node_modules
├── package-lock.json
├── package.json
├── public
│   ├── index.html
│   └── main.js
├── src
│   ├── App.jsx
│   └── index.jsx
└── webpack.config.js

src/index.jsをエントリーポイントとして、public/main.jsで出力する。

src/index.jssrc/App.jsxpublic/index.htmlを作成する。

App.jsx

import React from "react"

export const App = () => {
  return (
    <>
      <h1>React</h1>
    </>
  )
}

src/index.jsx

import React from "react"
import { createRoot } from "react-dom/client"

import { App } from "./App"

createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>React</title>
</head>
<body>
  <!-- rootにコンポーネントをマウントする -->
  <div id="root"></div>
  <script src="./main.js"></script>
</body>
</html>

2. インストール

JSX をトランスパイルするには@babel/preset-reactが必要。

npm i -D @babel/preset-react

3. 設定

webpack.config.jsを以下のように記述する。

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.jsx',
  output: {
    path: path.resolve(__dirname, 'public'),
    filename: 'main.js',
  },
  devServer: {
    static: "public",
    open: true
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx']
  }
};

設定例:TypeScript

Babel で TypeScript もトランスパイルできる。

1. インストール

Babel で TypeScript をトランスパイルするためには、TypeScript 本体であるtypescriptと、ts-loaderまたはbabel-loaderのパッケージが必要。

ts-loaderbabel-loaderの違いは、ts-loaderでは TypeScript の公式のコンパイラである tsc を使い、tsconfig.jsonを基に型チェックが行われるが、babel-loaderではtsconfig.jsonを使わず、型チェックが行われない。

2. 設定

webpack.config.jsts-loaderの設定を記述する。

module.exports = {
  module: {
    rules: [
      {
        // 拡張子がtsのファイルを対象
        test: /\.ts$/,

        // ts-loaderを使う
        use: "ts-loader",

        // node_modules/を対象外にする
        exclude: /node_modules/,
      },
    ],
  }
};


.babelrcに presets を追加する。

{
  "presets": ["@babel/preset-env", "@babel/preset-typescript"]
};

CSS の設定

JavaScript だけでなく CSS ファイルもバンドルすることができる。

1. インストール

CSS をバンドルするにはstyle-loadercss-loaderのパッケージが必要。

css-loaderは、CSSJavaScript に変換するパッケージ。

style-loaderは、バンドルされた CSS を HTML でスタイルシートとして読み込めるようにするパッケージ。

npm i -D style-loader css-loader

2. 設定

webpack.config.jsstyle-loadercss-loaderを使う設定を記述する。

module.exports = {
  module: {
    rules: [
      {
        // 拡張子がcssのファイルを対象
        test: /\.css$/,

        // 複数のloaderを使う
        use: ["style-loader", "css-loader"]
      }
    ]
  }
}

css-loaderCSSJavaScript にバンドルしてから、style-loaderで HTML で読み込めるようにするため、css-loaderを先に使う必要がある。

useでは後に書いた loader が先に使われるため、css-loaderを後に書く。

3. 実行

npm run devでバンドルを実行する。

Sass の設定

Sass は CSS をより便利に書ける上位言語。

最終的に CSS に変換するので、Webpack で Sass を使う際は CSS の設定が行われていることが前提。

1. インストール

Webpack で Sass を使うには、sass-loadernode-sassが必要。

npm i -D sass-loader node-sass

2. 設定

webpack.config.jsを以下のように記述する。

module.exports = {
  module: {
    rules: [
      {
        test: /\.(sass|scss|css)$/i,

        // sass-loaderを追加
        use: ["style-loader", "css-loader", "sass-loader"]
      }
    ]
  }
}