17
10

More than 5 years have passed since last update.

Webpack Level 1: 裸のWebpackのデフォルト動作を理解する

Last updated at Posted at 2018-07-31

コンテンツ

こんにちは!高野です。
さて僕はRailsエンジニアなのですが、実は今までwebpackが怖くてたまりませんでした。フロントエンド開発の際は create-react-appvue-cliangular-cli などを用いて自動生成される webpack.config.js を使うだけで、設定をいじろうなどと大それたことはしないよう気をつけていたのですが、そろそろ自分で設定ファイルを書けるようになりたいなと思い、色々と実験してみた備忘録を公開します。
僕と同じようにサーバーサイドを主戦場とする方や、webpackが何となく怖いという方、ぜひ一緒に勉強していきましょう。

webpackが理解しづらい理由

webpackは元々、モジュールバンドラと言って、複数のJSファイルを結合して1つのファイルにするためのツールです。Webページを読み込むに当たって、大量のJSファイルを読み込むより1回で全て読み込めた方が素早くページをロードできる、大規模な処理を複数ファイルに分けて書くことで機能単位に分割しやすくなるなどのメリットがあります。
が、webpackはプラグインを追加していくことで、当初のモジュールバンドラとしての役割だけでなく、開発時の様々な便利機能を提供することができるようになっています。例えば開発時にファイルの更新を検知して自動でブラウザをリロードしたり、変更点だけブラウザに反映してくれたりとかいったものが代表的ですね。
このように デフォルトの動作と設定ファイルによる動作、プラグインの提供機能などが多くありすぎて、ごちゃごちゃになってしまうことがwebpackの理解しづらさなのではないか と僕は考えました。そこで、今回は必要最低限の設定で、裸のwebpackがどのように動作するのかについて調べてみたいと思います。

環境

  • webpack 4.16.3
  • webpack-cli 3.1.0
  • webpack-dev-server 3.1.5

事前準備

  • プロジェクトを作成
$ mkdir webpack-level-1
$ cd webpack-level-1
$ npm init
  • webpackをインストール
$ npm install --save-dev webpack webpack-cli webpack-dev-server
  • 空の config ファイルを作成
webpack.config.js
module.exports = {};
  • バンドル対象のJSファイルを作成
src/index.js
console.log('Hello, webpack.');

実験: 裸の webpack を実行する

上記の状態で webpack を実行します。

$ webpack
Hash: b4b9534f490890150ac2
Version: webpack 4.16.3
Time: 85ms
Built at: 2018-07-31 08:42:39
  Asset       Size  Chunks             Chunk Names
main.js  960 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js 32 bytes {0} [built]

WARNING in configuration
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.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

バンドルできたようです。ここまでで下記のことがわかります。

  • src/index.js をデフォルトのエントリーポイントとしてバンドルを開始する
  • プロジェクトルートの webpack.config.js ファイルを設定ファイルとして読み込む
  • dist/ 配下に main.js というJSファイルを吐き出す

なお生成された main.js の中身を見てみると、我々が書いた console.log('Hello, webpack.') だけでなく、1000文字くらいのスクリプトになっていることが分かります。何をしているのかはよく分かりませんが、ただファイルを結合するだけでなく何かしら便利なことをしてくれているようです。

実験: 裸の webpack-dev-server を実行する

次に webpack-dev-server を使ってみましょう。 webpack-dev-server は開発時に便利な様々な機能を提供してくれますが、何も設定しない状態では「バンドルしたファイルをlocalhostからサーブする」「ファイルの更新を検知してバンドルし直す」というところまでやってくれます。
まずは必要なHTMLファイルを下記のように作ってみます。

index.html
<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <script type="text/javascript" src="./main.js"></script>
</body>
</html>

この状態で webpack-dev-server を実行してみます。

$ webpack-dev-server
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
⚠ 「wdm」: Hash: baee4eedcd5fedadd755
Version: webpack 4.16.3
Time: 404ms
Built at: 2018-07-31 09:11:24
  Asset     Size  Chunks             Chunk Names
main.js  139 KiB       0  [emitted]  main
Entrypoint main = main.js
 [2] multi (webpack)-dev-server/client?http://localhost:8080 ./src 40 bytes {0} [built]
 [3] (webpack)-dev-server/client?http://localhost:8080 7.78 KiB {0} [built]
 [4] ./node_modules/url/url.js 22.8 KiB {0} [built]
 [7] ./node_modules/url/util.js 314 bytes {0} [built]
 [8] ./node_modules/querystring-es3/index.js 127 bytes {0} [built]
[11] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {0} [built]
[12] (webpack)-dev-server/node_modules/ansi-regex/index.js 135 bytes {0} [built]
[13] ./node_modules/loglevel/lib/loglevel.js 7.68 KiB {0} [built]
[14] (webpack)-dev-server/client/socket.js 1.05 KiB {0} [built]
[15] ./node_modules/sockjs-client/dist/sockjs.js 177 KiB {0} [built]
[16] (webpack)-dev-server/client/overlay.js 3.58 KiB {0} [built]
[18] ./node_modules/html-entities/index.js 231 bytes {0} [built]
[21] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {0} [built]
[23] (webpack)/hot/emitter.js 75 bytes {0} [built]
[25] ./src/index.js 33 bytes {0} [built]
    + 11 hidden modules

実行したままの状態で http://localhost:8080 にブラウザからアクセスしてみると、先ほど作った空のHTMLファイルが返されます。
Developer ToolのNetworkを見てみると、バンドルされた結果が http://localhost:8080/main.js からサーブされていることが分かります。

localhost_8080.png

そのレスポンスの中身を見てみると、5,200行くらいのJSファイルになっていることからも分かるように、バンドルした結果だけでなく、ブラウザをコントロールするための websocket の処理などが追加されているようです。

さらに src/index.js を更新すると、自動でバンドルし直してくれます。
以上をまとめると、裸の webpack-dev-server のデフォルト動作は下記になります。

  • プロジェクトルートの index.html を localhost:8080 からサーブする
  • バンドルした結果を含むJSファイルを localhost:8080/main.js からサーブする
  • ファイルの変更を検知すると自動でバンドルし直してくれる

ちなみに、 webpack-dev-server を実行した状態で別プロセスでまた webpack-dev-server を実行すると、 localhost:8081 でサーバーが起動します。ポートが使われていることを検知すると自動でポートを変更してくれるみたいです。
他にも色々ありそうですが、裸の webpack-dev-server を理解するなら一旦ここまでで大丈夫でしょう。

実験: 設定ファイルに最低限の情報を書き込む

webpack.config.js を下記のように変更してみます。

webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: {
    path: path.resolve(__dirname, './build'),
    filename: 'bundle.js',
  },
};

path.resolve(__dirname, './build') というのは、 webpack.config.js から見た相対パス ./build を絶対パスに直してくれる関数です。 output.path は絶対パスでないとエラーが出るのでこういう書き方になっています。
エントリーポイントを変更したので index.js を app.js に変更してから webpack を実行してみます。

$ mv src/index.js src/app.js
$ webpack
Hash: 243ed1b1b7f9b93c9dc0
Version: webpack 4.16.3
Time: 86ms
Built at: 2018-07-31 08:58:37
    Asset       Size  Chunks             Chunk Names
bundle.js  960 bytes       0  [emitted]  main
Entrypoint main = bundle.js
[0] ./src/app.js 32 bytes {0} [built]

WARNING in configuration
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.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

すると今度は src/app.js がバンドル対象として読み込まれ、 /build 配下に bundle.js という名前でバンドル結果が吐き出されました。
このようにエントリーポイントと結果ファイルの生成場所を指定することができます。

まとめ

webpack-dev-server は開発時にlocalhostからファイルをサーブしたい時に使います。
本番環境にファイルをアップロードしたい時は、 webpack を使って本番用のファイルを生成します。
このような使い分けを前提に、設定ファイルやプラグインを使って、目的や要件に応じた開発環境を作っていくのがwebpackなのです。

以上が「裸のwebpackのデフォルト動作を理解する」でした。デフォルト動作を理解できると、なんだかwebpackと心を通わせることができそうな期待感が湧いてきますね。

次回 Webpack Level 2: 設定ファイルをカスタマイズする では、 webpack.config.js をカスタマイズしてみる実験をしています。是非ご覧ください。

参考

今回利用したソースコードは こちら です。

17
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
10