サイトアイコン 上尾市のWEBプログラマーによるブログ

「webpack実践入門」の感想・備忘録2

「webpack実践入門」の感想・忘備録1の続き

プラグイン

プラグインとは

ローダーはバンドル前に作用するが、プラグインはバンドルファイルに作用する。

ProvidePlugin

任意のモジュールを全てのファイル(モジュール)の変数として利用可能にするプラグイン。
ファイルごとにimport文で読み込む必要がなくなる。
npmパッケージのインストールは不要。webpackに組み込まれている。

  1. webpack.config.jsにwebpackのrequire文とpluginsプロパティを追加
const webpack = require('webpack');
// 〜省略〜
plugins: [
  // ProvidePlugin を利用する
  new webpack.ProvidePlugin({
    // 外部モジュールであるjqueryを、全てのファイル上で変数$として利用できるようになる
    $: 'jquery'
  })
]

これでimport $ from ‘jquery’;を書かなくても、全てのjsファイルで変数$が使えるようになる。

webpack-bundle-analyzer

バンドルされたモジュールのファイルサイズを確認できるプラグイン。

  1. npm install --save-dev webpack-bundle-analyzer
  2. webpack.config.jsにwebpack-bundle-analyzerのrequire文とpluginsプロパティを追加
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// 〜省略〜
plugins: [
  new BundleAnalyzerPlugin()
]

実行すると、一番上にバンドルしたファイル、その下にその中身が階層で表示される。

clean-webpack-plugin

バンドル時に、ouput.pathで指定したディレクトリ内のファイルを削除するプラグイン。

  1. npm install --save-dev clean-webpack-plugin
  2. webpack.config.jsにclean-webpack-pluginのrequire文とpluginsプロパティを追加
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// 〜省略〜
plugins: [
  new CleanWebpackPlugin()
]

便利な機能

エントリーポイントを複数指定する

entryが1つの場合は文字列で指定するが、複数の場合はオブジェクトで指定する。
バンドルファイル名には、filename: '[name].js',のようにenrtyのキー名を使うことができる。 (以下の例の場合、app.bundle.js と search.bundle.js が出力される)

// 1つの場合は文字列で指定する
// entry: './src/js/app.js',

// 複数の場合はオブジェクトで指定する
entry: {
  app: './src/js/app.js',
  search: './src/js/search.js'
},

// 出力の設定
output: {
  // 出力するファイル名
  filename: '[name].js',
  // 〜省略〜
},

watchモード

webpack.config.jsにwatch: tureを追加する、またはwebpackコマンドに–watchオプションを付与するとwatchモードとなり、ファイルが更新される度に自動的にバンドルが行われる。
npm srciptで
"dev": "webpack --watch --mode=development",
"build": "webpack --mode=production"
としてmodeとwatchモードを分けると便利。

webpack-dev-server

  1. npm install --save-dev webpack-dev-server
  2. webpack.config.jsのoutputプロパティにpublicPathを追加、devServerプロパティを追加
  3. webpack-dev-serverで実行
    (またはpackage.jsonのscriptに”start”: “webpack-dev-server”を追加してnpm run startとする)
output: {
  filename: 'bundle.js',
  path: path.resolve(__dirname, 'public/js'),
  publicPath: '/js/' // ブラウザからバンドルにアクセスする際のパス
},
// 〜省略〜
devServer: {
  open: true, // サーバー起動時にブラウザを自動的に起動する
  port: 9000,
  contentBase: './public' // コンテンツのルートディレクトリ
}

ソースマップ

ソースマップとはバンドルしたファイルと元のファイルを関連付けるファイルであり、バンドル前のコードを確認できるためデバッグがしやすくなる。
開発者ツールでは、sourcesタブのwebpack://の配下に圧縮前のファイルが表示される。
modeがdevelopmentの場合は、devtool: 'eval'としてソースマップが生成される。 ‘eval’はローダーで変換された後のコードなので、変換前のソースマップが必要な場合は’source-map’を指定する。

  1. webpack.config.jsにdevtoolプロパティを追
    devtool: 'source-map'

設定ファイルを分ける

本番用と開発用で設定ファイルを分ける場合は、実行時に–configオプションを指定する。
npm srciptで
"dev": "webpack --watch --mode=development --config webpack.dev.config.js",
"build": "webpack --mode=production --config webpack.prod.config.js"
として分けると便利。
共通部分をwebpack.base.config.jsのようなファイルに記述し、差分だけ別ファイルにしたい場合はwebpack-mergeを使う。

  1. npm install --save-dev webpack-merge
  2. 本番用、開発用設定ファイルに共通設定読み込み用の記述を追加
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.config.js');

// 共通設定(baseConfig)をマージする
module.exports = merge(baseConfig, {
  mode: 'development',
  devtool: 'source-map'
});

terser-webpack-plugin

productionモードで有効になるoptimization.minimizerを上書きするためのプラグイン。
productionではconsole.logやコメントを出力させたくない場合などに使う。

  1. npm install --save-dev terser-webpack-plugin
  2. webpack.base.config.jsにoptimization.minimizerの設定を追加
const TerserPlugin = require('terser-webpack-plugin');
// 〜省略〜
optimization: {
  minimizer: [
    new TerserPlugin({
      terserOptions: {
        compress: { drop_console: true }, // consoleを除去
        output: { comments: false }, // コメントを除去
      }
    })
  ]
}

最適化

Tree Shaking

Tree Shakingとは、デッドコード(使われていない不要なコード)を除去する機能のことである。webpack4では、productionモードでビルドすると自動的にTree Shakingを使ってビルドされる。
import { upperCase } from 'lodash-es';のようにES2015のimport/export構文(ES Modules)を使うと、Tree Shakingが行われる。
import _ from 'lodash-es';のようにモジュール全てをインポートするとTree Shakingは行われない。
※lodashはCommonJSなのでlodash-esを使う必要がある。

SplitChunksPlugin

複数のエントリーポイントで同じモジュールを利用している場合、デフォルトだとそれぞれのバンドルファイルにモジュールもバンドルされてしまう。 SplitChunksPluginを利用すると、共通で利用しているモジュールだけのバンドルファイルを別に生成してくれる。

例えば、エントリーポイントapp.jsとapp2.jsが共にjQueryとlodashを使っている場合、2つのバンドルファイルとは別にvendor.bunle.jsのようなファイルを生成してくれる。
SplitChunksPluginはnpmパッケージのインストールは不要。webpackに組み込まれている。

  1. webpack.config.jsにoptimization.splitChunksの設定を追加
optimization: {
  splitChunks: {
    cacheGroups: {
      // 今回のプロパティ名は vendor だが、ここは任意のもので良い
      vendor: {
        test: /node_modules/, // node_modules配下のモジュールをバンドル対象とする
        name: 'vendor', // 出力するファイル名 今回は 'vendor' で、output.filename が '[name].bundle.js' のため、vendor.bundle.js が出力される。
        chunks: 'initial', // 共通モジュールとしてバンドルする対象の設定
        // webpack はデフォルトでいくつかの splitChunks の設定が有効になる。enforceをtrueにすれば、それらの設定の
        // splitChunks.minSize, splitChunks.minChunks, splitChunks.maxAsyncRequests, splitChunks.maxInitialRequests を無効にできる
        enforce: true
     }
  }
}
モバイルバージョンを終了