最新版で学ぶwebpack 5入門
JavaScriptのモジュールバンドラ

416
407

webpack(ウェブパック)とはJSファイルをまとめる高機能なモジュールバンドラー。まとめることでウェブページのHTTPリクエストの数を減らしたり、高度なウェブアプリケーションの開発に役立ちます

連載ではTypeScriptBabelなどのES2015+の環境構築、ReactなどのJSライブラリの設定方法を網羅。サンプルファイルで詳しく解説します。

webpackの入門記事は他のサイトにもありますが、対象バージョンが古くて使えなかったりします。検索結果の上位の野良記事を参照にしたら古いバージョンの内容ばかり。解説記事通りにやったのにうまく動かない・・・なんて困った方も多いのではないでしょうか。本記事は常に最新版に対応させているので、安心して読み進めてください

※本記事では2023年3月現在のwebpack 5(2020年10月リリース)以上で解説しています。

本記事で解説していること

webpackの概要

webpackとはウェブコンテンツを構成するファイルをまとめてしまうツールです。一番多い使い方は、複数のJavaScriptを1つにまとめることでしょう。複数のJavaScriptをまとめるのは、いろんな利点があります。

モジュールが使える

ウェブのフロントエンド開発では、JavaScriptは処理内容に応じて、ファイルを「モジュール」としてわけて開発することがほとんどです。モジュールには標準仕様のECMAScript Modules(通称、ES ModulesやESMと呼ばれます)や、Node.jsで旧来より用いられているCommonJS形式のモジュールなど、さまざまなモジュールの形式があります。webpackはどの形式にも対応しており、モジュールをバンドルする(1つにまとめる)ことができます。

また、一般的なJSライブラリはモジュール形式で提供されており、これも同様にwebpackで取り込めます。

かつて、JavaScriptはscriptタグでJSライブラリを導入する方法が用いられていましたが、グローバルの変数名を汚染しあうという問題がありました。ES Modulesを使うと変数の競合やグローバル汚染を防げるので開発時の安全性が高まります。さらには、コードの可読性が上がり、開発作業の分担やテストがしやすくなり、再利用性や保守性のメリットが考えられます。

転送の最適化

ファイルを1つにまとめることはウェブコンテンツの読み込み性能向上に役立ちます。たとえば、HTTP/1.1接続ではブラウザとウェブサーバーの同時接続数が限られるため、複数のファイルの転送に時間がかかります。複数のJSファイルを1つにまとめてしまうことが一般的な解決案として知られています。

▲webpackを利用して制作したウェブサイト。リクエスト数が少ないためブラウザキャッシュのない状態でも300ミリ秒をきるほど爆速である

JSだけでなく、CSSや画像もバンドルできる

それだけでも便利なのですが、webpackはJavaScriptだけでなくスタイルシートや画像までもバンドルできてしまうのです。先述の転送の最適化につながるメリットです。

▲webpackはさまざまなアセットをJavaScriptファイルにまとめることができる

包括的な開発環境が整う

JSファイルの圧縮やソースマップに対応していたり、ローカルサーバーの起動まで包括的な制作環境としての機能まであります。タスクランナーのGulpやnpm scriptsだけでは、ツールの組み合わせが無限。「オレが数々の案件で作り込んだ秘伝のタレ」のように、設定ファイルが煩雑化しがちです。webpackであれば、はじめから最後までwebpack一式でツールを揃えられます。このあたりが、イマドキのフロントエンドエンジニアのツールと言われる所以ゆえんです。

webpackを導入しておけばフロントエンドエンジニアに必要な技術がひととおり揃う、ということが最大の利点でしょう。

導入手順

webpackを使う準備をしましょう。事前にNode.jsをインストールし、コマンドラインを使う準備をしておいてください。

  1. 公式サイトからNode.jsをインストールします
  2. コマンドラインを起動します (macOSだと「ターミナル」、Windowsだと「コマンドプロンプト」)

解説の手順はわずか2分半の動画に記録しておきました。動画を見ればwebpackの環境を誰でも確実に設定できます。記事を読み進めてわからない手順があれば、動画を見返してください。

コマンドラインでの操作

コンテンツのファイル一式が保存されるフォルダーを任意の場所に作成し、コマンドラインでその場所に移動します。cdコマンドで任意のフォルダーまで移動しましょう。「MyName/myproject」は仮の名前なので、好きなフォルダー名を指定ください。

▼ Windowsでの移動

cd C:¥Users¥MyName¥myproject

▼ macOSでの移動

cd /Users/MyName/myproject

次のコマンドを実行します。これを実行すると、プロジェクトの設定情報が記述されたpackage.jsonファイルが生成されます。

npm init -y

ターミナルでnpm initコマンドを使ってpackage.jsonを作成する

webpackを実行する為に、webpack本体をインストールします。npm installはインストールの命令、-Dはインストール先をdevDependenciesにするための指定、webpackはその名の通りインストールする対象です。

npm install -D webpack webpack-cli

npm installコマンドを使ってwebpack関連モジュールをインストールする

以上で、webpackを使用できる準備が整いました。

webpackでJSファイルをまとめる手順

モジュール方式でJavaScriptを書く理由

1つのJavaScriptファイルに長い処理を書くと、可読性が悪くなります。これを解決するには複数ファイルへ分割することでしょう。ウェブのフロントエンド界隈では、機能ごとに分割されたJavaScriptファイルのことを一般的に「モジュール」と呼びます

JavaScriptをモジュールで書くにはお作法があり、現在は標準仕様のES Modules形式で書くのが一般的です。

少し古いブラウザではJavaScriptのモジュールを取り扱うための仕組みがなかったため、モジュールを取り扱うための仕様が長いこと検討されてきました。代表的なものにCommonJS、AMD、ES2015のModules等があります。

webpackで、モジュールとしてのJavaScriptを結合していきましょう。

モジュール方式のJavaScriptを書いてみよう

ES ModulesのJavaScript処理を例にして説明します。ES Modulesをはじめて見る方は難しく思うかもしれませんが、これからのJavaScriptの基本知識になるはずなので頑張って読み進めてください。この記事で解説するサンプルはGitHubからダウンロードできます。

index.jssub.jsに定義されたhello()メソッドを呼び出す仕組みを考えてみます。ES Modulesの仕様に沿った記法としては、次のようなコードとなります。

▼index.js

// import 文を使って sub.js ファイルを読み込む。
import { hello } from "./sub";

// sub.jsに定義されたJavaScriptを実行する。
hello();

▼sub.js

// export文を使ってhello関数を定義する。
export function hello() {
  alert("helloメソッドが実行された。");
}

JavaScriptモジュールはこのままだと古いブラウザ(例:昔のInternet Explorer 11)で使用できなかったため、古いブラウザが解釈できる形に変換する必要があります。そこで登場するのがwebpackです。

webpackでJavaScriptモジュールを扱う

webpackを使うと、JavaScriptモジュールをブラウザで扱える形に変換できますindex.jsのようにメインとなる処理を行うJavaScriptファイル「エントリーポイント」と呼びます。エントリーポイントをコマンドでビルドします。

それでは、コマンドラインで次のビルドコマンドを入力してみましょう。

▼webpackによるビルド(コマンドライン)

npx webpack

任意のindex.jsファイルを用意したらnpx webpackコマンドで打ち込む

index.js内で必要なsub.jsが統合され、distフォルダーのなかにmain.jsとして出力されます。

webpackによって 一つのJSファイルになる

このwebpackで出力したdistフォルダー内のファイルmain.jsをHTMLで読みこむと、バンドルされたコードが実行されます。distフォルダー内にはindex.htmlファイルを用意しておきましょう(コード例)。

dist/index.htmlファイル

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <script src="main.js"></script>
</head>
<body>
</body>
</html>

ビルドしたファイルは次のリンクで確認できるので、見てみましょう。

あっけなくwebpackのビルドができましたね。webpackの基本的な使い方の紹介は以上となりますが、さらに覚えるべき役立つ知識があるので解説します。

webpackのバンドルの概要図

▲webpackは複数のファイルの依存関係を考慮したうえで自動的に結合する

package.jsonをカスタマイズする

npx webpackコマンドでビルドするのもシンプルですが、npm scriptsを使う方が便利です。npm scriptsとはコマンドのショートカット(エイリアス)を貼るための機能。package.jsonファイルのscriptsには、webpackのビルドコマンドを追加します。

package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4"
  },
  "private": true
}

package.jsonファイルには最低限scriptsdevDependencies指定が記述されてあれば使えます。mainauthorなどは消してしまって大丈夫です。

こうしておけば、npm run buildとコマンドラインで入力することで、内部的にwebpackが呼び出され、さきほどの手順と同じ結果が得られます。npm scriptsの詳細は記事「npm-scriptsのタスク実行方法まとめ」で詳しく解説してるので参考ください。

npm run build というショートカットで webpackを呼び出すことができる

webpack.config.jsをカスタマイズする

webpack.config.jsファイルを用意することで、webpackの挙動を調整できます。

よく使う設定として、エントリーポイントを指定するentryと、出力フォルダーをカスタマイズするoutputがあります。必須ではないもの、よく使うオプションのため必ずおさえておきましょう。次のように指定します。

▼webpack.config.jsファイル

module.exports = {
  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: `./src/index.js`,

  // ファイルの出力設定
  output: {
    //  出力ファイルのディレクトリ名
    path: `${__dirname}/dist`,
    // 出力ファイル名
    filename: "main.js"
  }
};

webpackでは、エントリーポイントを指定しなければ自動的に「src/index.js」がエントリーポイントに、出力先を指定しなければ自動的に「dist/main.js」に出力されます。

output.pathオプションを省略することもでき、その場合、出力ファイルは「dist」フォルダーにファイルが作成されます。

▼webpack.config.jsファイル

module.exports = {
  // メインとなるJavaScriptファイル(エントリーポイント)
  entry: `./src/index.js`,

  // ファイルの出力設定
  output: {
    // 出力ファイル名
    filename: "main.js"
  }
};

webpackではウェブコンテンツを制作に役立つさまざまな機能があります。たとえば、webpackで出力したJavaScriptファイルは大きなファイル容量となるので、圧縮しておきたいと考える人も多いでしょう。そういった要望に応える機能が備わっています。

webpackでコードの圧縮とソースマップを有効にする

JavaScriptの開発では、元のソースファイルとの関連性を示すソースマップが欠かせません。また、ウェブサイトへの公開時にはウェブページの読み込みを早くするために、ファイル容量を圧縮することも重要でしょう。webpackでは設定ファイルの記述によって、それらをカスタマイズできます。

webpackの設定ファイル

webpackの設定ファイルには次のように記述します。modedevelopmentを記述することでソースマップを有効にします。逆に、modeの部分でproductionを指定することで、JavaSciptのコードを圧縮できます。開発時にはdevelopmentを指定し、ウェブサイト公開時にはproductionに設定するのがいいでしょう。

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: "development"
};

以上で設定は完了です。webpack.config.jsファイルにdevelopmentを指定を指定した場合は、npm run buildコマンドを入力すると、srcフォルダーに配置したJSファイルがコンパイルされ、distフォルダーにmain.jsファイルが出力されます。

webpack.config.jsファイルにproductionを指定を指定した場合は、dist/main.jsファイルの中身はムダなコメントが省略され、ファイル容量が最小化されていることが確認できるでしょう。

ここの手順をサンプルファイルとしてGitHubで公開していますので、参考ください。

webpackでローカルサーバーを起動し、変更時にブラウザをリロードする

毎回ビルドコマンドをコマンドラインで打ち込むのは効率的でありません。ファイルの変更を検知し(watchともいいます)、自動的にビルドコマンドを実行し、ブラウザをリロードする・・・といった手順を自動化できます。類似の技術として「lite-server」や「BrowserSync」といったものがありますが、それに近いものだと考えていいでしょう。

▲webpack-dev-serverの実行例。JavaScriptを編集すると、即座にブラウザが結果を反映する。ローカルのウェブサーバーとしても利用できる。

「webpack-dev-server」はとても便利な機能です。わずかな設定でできるので構築してみましょう。

ビルド時間の短縮に効果的でもある

webpackは初回ビルドと二度目以降のビルドでは、かかる時間が変わります。二度目以降のビルドは、差分ビルドとして時間が大幅に短縮されます。そのため毎回、webpackのビルドコマンドを使うのは、ビルド時間が余計にかかり時間のムダです。ビルド短縮のため、webpack-dev-serverもしくは後述のwatch機能は必ず利用しましょう

npmモジュールのインストール

webpack関連モジュールとwebpack-dev-serverモジュールをインストールしましょう。

npm i -D webpack webpack-cli webpack-dev-server

これをインストールすると、package.jsonファイルは次の内容になります。scriptsは自前のビルドコマンドとして"start": "webpack serve"を記述しておくのがポイントです。

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack",
    "start": "webpack serve"
  },
  "devDependencies": {
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^5.0.4"
  },
  "private": true
}

webpackの設定ファイル

webpackの設定ファイルには次のように記述します。devServerにルートフォルダーを設定します。open: trueを指定しておくと、自動的にブラウザが立ち上がります。

▼webpack.config.jsファイル

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: "development",

  // ローカル開発用環境を立ち上げる
  // 実行時にブラウザが自動的に localhost を開く
  devServer: {
    static: "dist",
    open: true
  }
};

以上で設定は完了です。npm run startコマンドを入力しましょう。もしくは、npx webpack serveコマンドでも起動できます。自動的にブラウザが起動しローカルホストで表示されます。ファイル保存時にブラウザが自動的にリロードするので、コーディング作業が楽になるでしょう

ここの手順をサンプルファイルとしてGitHubで公開していますので、参考ください。

ファイル変更時に差分ビルドを。ウォッチを利用する

webpack-dev-serverはとても便利ですが、ブラウザで確認する必要がないときは機能が多すぎて余分に思うかもしれません。JavaScriptをビルドしたいだけであれば、watch機能を利用するがいいでしょう。watch機能を利用するにはコマンドラインの引数に「–watch」を追加するだけです。

npx webpack --watch

もしくは、package.jsonファイルのscriptsは自前のビルドコマンドとして"start": "webpack --watch"を記述しておくのもいいでしょう。実行コマンドはnpm run watchとなります。

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch"
  },
  "devDependencies": {
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4"
  }
}

先述の通り、buildするよりもwatchを使ったほうが差分ビルドで高速になるので、積極的にwatchを利用するようにしましょう。

タスクランナーとの使い分け

webpackはこうした性質上、タスクランナーであるGulpGruntの代わりとして紹介されることがしばしばあります。Googleトレンドで見ても、webpackは人気です。

webpackとgulpとgruntの人気経過

2015年4月~2018年3月のGoogleトレンド調査(カテゴリー:コンピュータ)

タスクランナーでできることの多くはwebpackでも可能です。しかし、プロジェクトによってはタスクランナーGulp、Gruntの資産があり、webpackを部分的に採用したいケースもあるでしょう。また、webpackは「CSSや画像を含むあらゆるアセットファイルをJavaScriptとして出力する」ことが基本的な使い方となっているため、CSSや画像をそのまま扱いたい時はタスクランナーが必要になります。

npm trendsでもwebpackが優勢

他のモジュールバンドラーとの性能比較

性能面での比較

モジュールバンドラーとして知られているのはwebpackだけではありません。他にも類似のツールがあるので、性能面で違いはあるのかを検証しました。有名どころのnpm modulesを3つ利用しJavaScriptをバンドルする形での比較検証です。利用方法の制約から各ツールを完全に同一条件で比較できたわけではないので、「この技術を使った場合、こういう書き方をするのでこのぐらいの結果になる」という参考値としてとらえてください。

  • rollup : 0.56
  • webpack@4 : 4.1
  • webpack@3 : 3.11
  • fuse-box : 3.1
  • browserify : 16.1
  • parcel-bundler : 1.6

容量に関しては、webpackとrollupがもっとも小さくなりました。webpackはES ModulesをサポートしておりTree Shaking(未使用のモジュールを省いてバンドルする機能)や、モジュールの連結機能(可能な場合は複数のモジュールを1つに連結するconcatenateModulesオプション)を搭載していることが効果的だったようです。

ビルド時間に関してはwebpack 4(developモード)がもっとも高速でした。最新版webpackのリリースで「Build times decreased from 60 to 98%!!(意訳:ビルド時間は60%から98%に減少)」と紹介されているように、従来のwebpack 3よりも高速化したことが確認できました。

検証の条件・詳細とソースコードはGitHubで公開しています(「ベンチマークのソースコード」)。

ビルド時間の短さや成果物の容量から判断しても、webpackは他のツールよりも全般的に高性能であるといえそうです。もちろん、各々のツールには解決しようとしている課題が異なるので特性や使い方に違いがあります。さらに、性能は検証の条件で差がでるでしょうから、採用の前には皆さんのプロジェクトや環境で目的が合致しているか、性能に問題がないか試験されることをオススメします。

トレンドの比較

かつてはBrowserifyRequireJSといったツールもありました。npm trendsで調べたところ、webpackの利用が右肩上がりで他を圧倒していることがわかります。

各種バンドルツールのトレンド推移 | npm trends

BrowserifyはCommonJS仕様がベースで(module.exportsrequire()のような独自に定義された変数やメソッドを使う仕様)、Tree Shakingが使えないという点で旧世代のツールです。枯れた技術としてはRequireJSやBrowserifyの利点はありますが、標準仕様のES Modulesをネイティブで利用できるwebpackのほうが将来性があるといえそうです。

webpackの他には、Parcelというツールがあります。webpackに比べて設定が少ないことが特徴です。本サイトでも解説記事をたくさん書いていますので、あわせてご覧ください。

他にもViteが注目されています。ビルド時間が少ないことが特徴です。

webpackは次世代の標準となりうる技術

大規模なJavaScriptの開発にはモジュールシステムの導入は必須。webpackはJavaScriptのモジュールを扱いやすくするのはもちろん、他のアセットファイルの取り扱いにも長けているという便利な技術です。実際のJavaScript開発ではBabelやTypeScriptを利用することがほとんどでしょう。

続編記事「webpack + BabelでES2015+ビルド環境の構築」と「webpack + TypeScriptの環境構築」で使い方を説明してますので、あわせてご覧ください。

筆者もここ最近webpackを使っていますが、多機能で使いやすく、現在人気になっているのも納得できました。トレンドから見てもタスクランナーと並んで今後標準のウェブ開発技術になることが予想されます。是非この機会に触れてみてください。

連載一覧

※この記事が公開されたのは8年前ですが、9か月前の3月に内容をメンテナンスしています。

池田 泰延

ICS代表。筑波大学 非常勤講師。ICS MEDIA編集長。個人実験サイト「ClockMaker Labs」のようなビジュアルプログラミングとUIデザインが得意分野です。

この担当の記事一覧