9
6

More than 5 years have passed since last update.

Webpackでの一括読み込み(その2)

Last updated at Posted at 2018-01-21

以前にWebpackでフォルダ内の全ファイルを一気にrequireするという記事(以下、「前記事」とします)を書いたのですが、これでは微妙に気になる点が出てきました。

今回は、その点をクリアするための別な手法を紹介します。

メリットとデメリット

前記事で挙げた、require.contextを使う手法のメリットは、以下のようなものとなります。

  • Webpackの標準機能で片付いて、他のライブラリを使う必要がない
  • ファイル名もJavaScriptで取得できるので、「requireした結果をフォルダ構造に従って変数に代入する」というような操作も、そのまま実装できる

一方で、上2つのメリットはそのままデメリットに転じえます。

  • require.contextはWebpack独自仕様なので、Webpackにロックインされてしまう
  • 「読み込みの副作用だけが必要で、結果は使わない」というような事例を代表として、ファイル名が全く不要な場面でも、ファイル名までバンドルに含まれてしまい、容量を消費する

今回は、後者の「不要なファイル名が容量を消費する」という点が気になったので、改善のために別手法を取ってみることにしました。

globという「共通言語」

Unix系で、複数のファイルを一気に選択するための手法として、ワイルドカードを拡張した「glob」が一般に使われます。そして、このglobを読み込みに使えれば…ということはみんな考えるもので、Browserifyにはrequire-globifyが、Rollupにはrollup-plugin-glob-importがあるなど、各ツールで使えるようになっています。そして、もちろんWebpackにもimport-glob-loaderのようなglob対応ローダーがあります1

Webpackのimport-glob-loaderは、プレローダーとして仕掛ける、あるいは必要箇所だけimport-glob-loader!./path/to/import.jsのようにして呼び出すこととなります。

webpack.config.js
module: {
    rules: [{
        test: /\.js$/,
        enforce: "pre",
        loader: 'import-glob-loader'
    }]
}

注意点

使う上で、いくつか注意点があります。

  • 名前の通り、デフォルトではimportのみに対応します。設定すればrequireに反応させられなくもないかもしれませんが、どうなるかはわからないです。
  • importのある行で、ファイル名以外の部分はすべてコピーされますので、JavaScriptで使う場合は、副作用のみを拾うimport '(glob-pattern).js';の形以外は事実上使えません(変数名が衝突してしまいます)。
  • CSS系の@importにも使えます。
  • これはimport-glob-loaderに限らないWebpackの挙動だと思われるのですが、importで書いたものは宣言だからかモジュールの最上部に移動します。ロード順を管理する必要がある場合にimportrequireを混ぜると、思わぬ挙動になりかねないので、そんなことは避けましょう。

実際にやってみた効果

200個ほどrequireしているものをrequire.contextから移行してみたところ、バンドル全体で90.0KB→88.2KBと、1.8KBほどの削減になりました。

参考


  1. なお、これらはすべてglob部分をnode-globに依存しているので、対応するglob文法も同じです。 

9
6
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
9
6