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

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

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

※本記事では2018年4月現在最新のNode.js v9.11、webpack 4.5で解説しています。

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

webpackの概要

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

転送の最適化

まず、HTTP/1.1接続ではブラウザとウェブサーバーの同時接続数が限られるため、複数のファイルの転送に時間がかかります。複数のJSファイルを一つにまとめてしまうことが一般的な解決案として知られています。

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

モジュールが使える

複数のJSファイルを一つにまとめるだけなら他のツールでもできますが、webpackの場合は標準仕様のES Modulesが使えたり、node_modulesのモジュールを結合できるといったメリットがあります。

標準のES Modulesを使うと変数の競合やグローバル汚染を防げるので開発時の安全性が高まります。さらには、コードの可読性が上がり、開発作業の分担やテストがしやすくなり、再利用性や保守性があがります。

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

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

160519_webpack_is

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

包括的な開発環境が整う

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

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

導入手順

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

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

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

コマンドラインでの操作

コンテンツのファイル一式が保存されるフォルダーを任意の場所に作成し、コマンドラインでその場所に移動します。cdコマンドで任意のフォルダーまで移動しましょう。

 ▼ Windowsでの移動

cd C:¥Users¥MyName¥myproject

 ▼ macOSでの移動

cd /Users/MyName/myproject

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

npm init -y

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

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

npm i -D webpack webpack-cli

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

以上で、webpackを使用できる準備が整いました。次はJavaScriptのモジュールバンドルの方法を解説します。

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

今の時代はモジュール方式でJavaScriptを書くのが当たり前

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

160519_javascript_module

JavaScriptをモジュールで書くにはお作法があり、2018年現在は標準仕様のECMAScript Modules(略してES Modules、もしくはESM)で書くのが一般的です。

少し古いブラウザでは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モジュールはこのままだと古いブラウザ(例:IE 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で読みこむと、バンドルされたコードが実行されます。

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

あっけなくwebpackのビルドができましたね。フォルダー構造もいたってシンプルなのは、webpack 4になって構成が簡単に組めるようになったためです。webpackの基本的な使い方の紹介は以上となりますが、さらに覚えておいたほうが役立つ知識があるので解説していきます。

160519_webpack_js_bundle

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

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

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

package.jsonファイル

{
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14"
  }
}

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

こうしておけば、npm run buildとコマンドラインで入力することで、内部的にwebpackが呼び出され、先程の手順と同じ結果が得られます。npm scriptsの詳細は記事「Node.jsユーザーなら押さえておきたい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 4では、エントリーポイントを指定しなければ自動的に「src/index.js」がエントリーポイントに、出力先を指定しなければ自動的に「dist/main.js」に出力されます。

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

▼webpack.config.jsファイル

module.exports = {

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

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

次はwebpackでJavaScriptファイルをminifyする方法、ソースマップを使う方法、開発サーバーを立ち上げる方法を紹介します。

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-dev-server"を記述しておくのがポイントです。

▼package.jsonファイル

{
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server"
  },
  "devDependencies": {
    "webpack": "^4.5.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.1"
  }
}

webpackの設定ファイル

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

▼webpack.config.jsファイル

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

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

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

ここの手順をサンプルファイルとして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": "^4.5.0",
    "webpack-cli": "^2.0.14"
  }
}

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

次はタスクランナーとしての使い分け方を紹介します。

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

webpackはこうした性質上、タスクランナーであるGulpGruntの代わりとして紹介されることがしばしばあります。Googleトレンドで見ても、2017年4月現在ではタスクランナーGulpと肩を並べるほどwebpackは人気です。

webpackとgulpとgruntの人気経過

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

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

webpackとタスクランナーは併用して使うことも選択肢の一つのです。Gulpとwebpackを連携するための方法は、筆者のQiitaの記事「Gulpで始める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(未使用のモジュールを省いてバンドルする機能)や、モジュールの連結機能(可能な場合は複数のモジュールを一つに連結するconcatenateModulesオプション)を搭載していることが効果的だったようです。

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

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

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

トレンドの比較

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

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

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

2017年12月に新しいバンドルツール「Parcel」が話題になりました。設定ファイルが不要であり手軽ですが、ほとんどカスタマイズできません。記事「設定ファイル不要のParcelでTypeScriptをコンパイル・バンドルしたら拍子抜けするほど簡単だった – Qiita」で試しましたが、webpackと比べるとParcelは案件で使うのはまだ早い印象を持ちました

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

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

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

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

連載一覧

(編集部注*この記事は2016年5月23日に公開された記事を再編集したものです)