Webpackの基本から実践的な使い方まで完全ガイド

2024/12/25に公開

はじめに

フロントエンドエンジニアとして仕事をしているもののあまり触れる機会がないものの一つがWebpackではないでしょうか。

おおよそのケース、プロジェクトが始まるタイミングで定義されてしまっているためそんなに頻繁に扱う機会はない。

でも稀にパッケージのバージョンアップや新しいディレクトリに作成したコードや画像などのアセットがビルドに含まれないなどのトラブルで見る必要が出てくることがあります。

そんな私もWebpack 4から5にバージョンアップをつい先日行いまして非常に苦労しました。

webpackの基礎的な内容を理解してきたるべき日に備えるそんな記事となっております。

webpack公式サイト

https://webpack.js.org/

webpackは様々な環境で使うことができる便利なツールで今回の記事で全て書くのが難しいためReact、TypeScriptを使った環境については別の記事としてご紹介しています。

https://shinagawa-web.com/blogs/webpack-react-typescript

webpackとは

webpackは、モジュールバンドラというツールで、主にJavaScriptのコードやその他のリソース(CSS、画像、フォントなど)を1つのバンドルファイルにまとめるために使われます。

これにより、ウェブアプリケーションを効率的に配信できるようになります。

具体的には、Webpackは以下のことを行います:

  1. モジュールバンドリング
    複数のJavaScriptファイルを1つの大きなファイルや複数の小さなファイル(チャンク)にまとめます。これにより、複数のリソースを読み込む回数が減り、パフォーマンスが向上します。

  2. トランスパイル
    ES6+のコードやTypeScript、さらにはJSX(Reactで使われる)などを、ブラウザでサポートされている形式に変換します。

  3. アセットの管理
    画像、フォント、スタイルシートなどの非JavaScriptリソースも処理できます。これらは適切な形式に変換されたり、URLが自動で変更されたりします。

  4. コード分割
    アプリケーションの異なる部分(ページごとなど)を異なるファイルとして出力することができ、最初に読み込む必要のないコードは後から必要に応じて読み込まれます。

  5. プラグインとローダー
    Webpackではプラグインやローダーを使って、コードの最適化や、リソースの処理方法をカスタマイズすることができます。ローダーはファイルを変換するために使用され、プラグインはビルドのプロセスを拡張します。

最小構成でwebpackを始める

ということで早速webpackを使いながら少しずつwebpackの良さを理解していきましょう。

webpack-tutorialというディレクトリを作成しNode.jsのプロジェクトとして初期化します。

npm init

途中いろいろ聞かれますがEnter連打で問題ありません。

Image from Gyazo

webpackのインストール

下記コマンドでwebpackをインストールします。

npm i -D webpack webpack-cli

CLIから使うのでwebpack-cliも一緒にインストールしておきました。

サンプルのコードの準備

Javascriptのサンプルコードをsrc/index.jsとして用意します。

index.js
function component(name) {
  const element = document.createElement('div');

  element.innerHTML = `Hello ${name}`

  return element;
}

document.body.appendChild(component('World'));

続けてそれを読み込むHTMLファイルを作成しプロジェクトトップに保存します。

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>webpack tutorial</title>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>

作成したらindex.htmlファイルをブラウザで開いて、Hello Worldと表示されることを確認します。

Image from Gyazo

webpackでJavaScriptファイルのバンドル

サンプルのコードが用意できましたので早速webpackでバンドルしてみます。

npx webpack

すると新しくファイルが/dist/main.jsとして作成されました。

Image from Gyazo

ファイルを確認してみましょう。

整形前

main.js
document.body.appendChild(function(){const e=document.createElement("div");return e.innerHTML="Hello World",e}());

整形後

main.js
document.body.appendChild(
  (function () {
    const e = document.createElement('div');
    return (e.innerHTML = 'Hello World'), e;
  })()
);

サンプルのコードと書き方は違えど同じ処理のコードが生成されています。

それではこのコードが動くのか念のため確かめるべくHTMLファイルの読み込むjsファイルを変更して確認します。

/dist/index.htmlと保存先のディレクトリをプロジェクトトップから変更した上で、jsファイルの読み込み先を修正。

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>webpack tutorial</title>
  </head>
  <body>
-     <script src="./src/index.js"></script>
+     <script src="./main.js"></script>
  </body>
</html>

再びブラウザで確認します。

Hello Worldと表示されてますのでwebpackでバンドルしたファイルが正常に動くことを確認できました。

Image from Gyazo

ここまでwebpackに関する設定なく動きました。

webpack単体で扱う分には実はそれほど難しくない仕組みではあります。

とは言えこれだけで実務で使っていくには厳しいかと思いますので少しずつwebpackを掘り下げていきます。

ファイルの変更検知

webpackにはファイルの変更を検知して自動的に再バンドルするwatchモードがあります。

npx webpack --watch

こうしておくことでjsファイルを書き換えた際に再バンドルしブラウザでも変更内容がすぐ反映されます。

index.js
- document.body.appendChild(component('World'));
+ document.body.appendChild(component('Test'));

Image from Gyazo

古いブラウザへの対応

Babelは、JavaScriptのコンパイラ(トランスパイラ)で、最新のJavaScriptコードを古いブラウザでも動作する形に変換するためのツールです。

主にモダンなJavaScript機能を使用したコードを、互換性のないブラウザ向けに変換するために使われます。

  1. トランスパイル(変換)
    ES6+(ECMAScript 2015以降)の新しい構文や機能を、ES5(古いブラウザがサポートするバージョン)に変換します。
    例: constやletをvarに変換、arrow functions(アロー関数)を通常の関数に変換。

  2. Polyfillの提供
    新しいJavaScript機能が古い環境で動作しない場合、Babelはcore-jsや@babel/polyfillを通じてその機能を再現するコードを追加できます。
    例: PromiseやArray.includesなど。

  3. ReactやTypeScriptのサポート
    JSX(Reactで使われる特殊な構文)を通常のJavaScriptに変換できます。
    TypeScriptコードもBabelを使ってJavaScriptに変換可能です(ただし型チェックは行いません)。

  4. プラグインとプリセット
    Babelは拡張可能な仕組みを持ち、プラグインやプリセットを通じて変換内容をカスタマイズできます。
    プリセット: 一連のプラグインをまとめたもの(例: @babel/preset-env)。
    プラグイン: 特定の変換を担当するモジュール(例: @babel/plugin-transform-arrow-functions)。

Babel公式

https://babeljs.io/

先ほどのコードではconstが使われておりこれはES6から対応している機能となります。

そのためES5までしか動かないブラウザのバージョンでは問題となります。

そこでBabelを使いES5へ変換を行います。

webpackによるバンドルももちろん行うためBabelとwebpackの連携も必要となってきます。

Babelの導入

下記のコマンドでBabelをインストールします。

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

@babel/preset-envはES6 -> ES5に変換する際に必要となります。

.babelrcファイルをプロジェクト直下に作成し先ほどインストールしたプリセットを指定します。

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

webpackとの連携

webpackではローダーと呼ばれるプログラムを利用して変換に関する設定を行なっていきます。

ES6 -> ES5に変換するローダーとしてbabel-loaderを使うためインストールします。

npm i -D babel-loader

webpackのコンフィグでローダーを設定します。

webpack.config.js
/** @type {import('webpack').Configuration} */
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
      },
    ],
  },
};

今回の設定では.jsファイルに関してはbabel-loaderで変換を行います。

Babelの動作確認

設定完了しましたのでwebpackでバンドルします。

npx webpack

すると今度は出力されたjsファイルがこれまでと異なっていることがわかります。

constも使われなくなりました。

main.js
(() => {
  var e;
  document.body.appendChild((((e = document.createElement('div')).innerHTML = 'Hello '.concat('Test')), e));
})();

ES5の形式でjsファイルが作られることを確認でき古いブラウザでも動くようになりました。

CSSをバンドルする

jsファイルのバンドルと古いブラウザへの対応方法について見てきました。

次はCSSをwebpackで取り扱えるようにしていきます。

ローダーのインストール

JavaScriptコードの中でCSSをインポートし、それをHTMLの<style>タグとして適用する場合に2つのローダーが必要となります。

  1. css-loader
    CSSファイルをWebpackが認識してバンドルに含めます。

  2. style-loader
    CSSをHTMLの<style>タグに挿入します。

npm i -D style-loader css-loader

webpackにローダーの設定

2つのローダーを.cssファイルの時に扱うよう設定します。

webpack.config.js
/** @type {import('webpack').Configuration} */
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
      },
+       {
+         test: /\.css$/,
+         use: ["style-loader", "css-loader"],
+       },
    ],
  },
};

配列でローダーを定義する場合、配列の最後尾から順に適用されます。

css-loader -> style-loader の順で動くこととなります。

サンプルコードの準備

CSSファイルを/src/styles.cssに作成します。

styles.css
body {
  padding: 40px;
  color: blue;
}

JavaScriptファイルでCSSファイルを読み込みます。

index.js
+ import './styles.css'

動作確認

設定完了しましたのでwebpackでバンドルします。

npx webpack

ブラウザで確認すると文字が青になっておりCSSが正しく適用されていることがわかります。

Image from Gyazo

webpackのモード

これまでwebpackの実行時に警告が出ていました。

The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.

modeオプションが設定されていません。そのため、Webpackはこの値をproductionにフォールバックします。
developmentまたはproductionを設定することで、各環境に適したデフォルト設定を有効にできます。

これまではproductionとしてバンドルされていました。

webpack 5では3種類設定できるようです。

  1. development
  2. production
  3. none

試しにdevelopmentモードでwebpackを実行してみましょう。

npx webpack --mode=development

/dist/main.jsをみてみると先ほどとは違いコメントが書かれています。

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _styles_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./styles.css */ \"./src/styles.css\");\n\nfunction component(name) {\n  var element = document.createElement('div');\n  element.innerHTML = \"Hello \".concat(name);\n  return element;\n}\ndocument.body.appendChild(component('Test'));\n\n//# sourceURL=webpack://webpack-tutorial/./src/index.js?");

index.jsのバンドル結果だというのがコメントから確認できます。
productionモードにはなかったコメントなどが入るようになり開発段階では役に立ちそうです。

さいごに

ここまでwebpackの基本的な使い方や設定方法についてご紹介しました。

webpackは非常に多機能で強力なツールですが、その分設定が少し複雑に感じることもあります。

しかし、少しずつ学んでいくことで、アプリケーションのパフォーマンス向上や開発効率を大きく改善することができます。

今回紹介した内容を参考に、自社のプロジェクトに必要な設定を追加し、webpackの力を存分に活用していきましょう。

おすすめの記事

React + TypeScriptの環境をWebpackでビルドする記事をご紹介します。

https://shinagawa-web.com/blogs/webpack-react-typescript

記事に関するお問い合わせ📝

記事の内容に関するご質問、ご意見などは、下記よりお気軽にお問い合わせください。
ご質問フォームへ

技術支援などお仕事に関するお問い合わせ📄

技術支援やお仕事のご依頼に関するお問い合わせは、下記よりお気軽にお問い合わせください。
お問い合わせフォームへ