webpackで開発環境と本番環境を作成する

前提条件

Node.jsがインストールされており、npmとnpxコマンドが実行可能な状態であること。

最終的なファイル構成

project
  |
  `--- /node_modules
  |
  `--- /src
  |      |
  |      `--- /js
  |             `--- app.js
  |
  `--- /dist
  |      |
  |      `--- /js
  |      |      `--- bundle.js     <--- webpackで生成される
  |      |      `--- bundle.js.map <--- webpackで生成される
  |      `--- index.html
  |
  `--- package-lock.json
  `--- package.json
  `--- webpack.common.js
  `--- webpack.dev.js
  `--- webpack.prod.js

パッケージのインストール

  • webpack
  • webpack-cli
  • @webpack-cli/serve
  • webpack-dev-server
  • webpack-merge
  • path

上記のパッケージをインストールする。

npm install --save-dev webpack webpack-cli @webpack-cli/serve webpack-dev-server webpack-merge

設定ファイル作成

webpackの設定ファイルを作成する。@webpack-cli/initをインストールすることでコマンドでひな形を作成することも可能らしい。

今回は開発環境用と本番環境用で、webpackの設定ファイルを分けることにした。

共有設定ファイル

下記内容でwebpack.common.jsを作成する。

const path = require('path');
module.exports = {
  entry: [ path.join(__dirname, 'src', 'js', 'app.js') ],
  output: {
    path: path.join(__dirname, 'dist', 'js'),
    publicPath: '/js/',
    filename: "bundle.js",
    chunkFilename: '[name].js'
  },
  target: ["web", "es5"],
  resolve: {
    extensions: ['.js', '.jsx']
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    watchContentBase: true,
    inline: true,
    hot: true,
    host: 'localhost',
    port: 8080,
    open: true,
  },
};
entry

ここに指定されたファイルを元に、モジュール間の依存関係が解析され、バンドルプロセスが実行される。

output.path

絶対パスでバンドルファイルの出力先を指定する。

output.publicPath

バンドルファイルが存在するパスを指定する。
正しく設定されていないと、webpack-dev-serverがうまく動かなかったり、画像やファイルの読み込み、遅延読み込みなどでエラーが発生する可能性がある。

target

指定されたプラットフォームで利用できるようにビルドされる。デフォルトではブラウザ向けにビルドされるようになっている。ECMAScriptのバージョンを指定することもできる。

resolve

モジュールリクエストの解決方法を変更するためのオプション。
webpackはresolve.extensionsに設定された拡張子を使い、モジュールの探索用パスを生成するらしい。

devServer

webpack-dev-serverに渡すオプションを指定できる。
ちなみに、webpack-dev-serverは、ビルドしたバンドルをメモリに保持する。

開発環境用設定ファイル

次に下記内容で、開発環境用にwebpack.dev.jsを作成する。

const path = require('path')
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')

module.exports = merge(common, {
    entry: ['webpack-dev-server/client?'],
    mode: 'development',
    devtool: 'eval',
})

entryにwebpack-dev-serverのエントリーポイントを指定している。これはHMR(Hot Module Replacement)を有効にするために必要なようだ。

mode

指定されたモードに応じて、ビルド設定が最適化される。
利用可能な値は、developmentとproduction、noneの3種類。

devtool

ソースマップの生成について、設定することができる。
今回は開発ビルドに推奨されるevalと、本番ビルドに推奨されるsource-mapを指定した。

本番環境用設定ファイル

最後に下記内容で、本番環境用にwebpack.prod.jsを作成する。

const path = require('path')
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')

module.exports = merge(common, {
    mode: 'production',
    devtool: 'source-map',
})

package.jsonのmain

package.jsonのmain部分はwebpack.common.jsにする。

ビルドコマンド

.\node_modules.bin\webpack --config webpack.prod.js

上記のようにwebpackを実行することも可能だが、下記のようにpackage.jsonのscriptsにコマンドを追記する方が楽だと思う。

{
  // ....
  "scripts": {
    "build": "webpack --config webpack.prod.js",
    "start": "webpack-cli serve --config webpack.dev.js"
  },
  // ....
}

実際にコマンドを実行する場合は、下記のようになる。

本番環境

下記コマンドでdist内のjsフォルダにbundle.jsとそのソースマップが生成される。

npm run build

index.htmlは自動で生成されないので、distフォルダ内に適当に作成する。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Hello World</title>
    </head>
    <body>
        <script src="js/bundle.js"></script>
    </body>
</html>

開発環境

下記コマンドでwebpack-dev-serverが立ち上がり、ブラウザが起動する。

npm run start

参考