はじめに
1年以上前ですがこんな記事を書きました。
このときは webpack-dev-server をスタンドアロンなサーバーとして使う方法しか知らなかったのですが
既存の Express アプリに組み込んで使うこともできます。
そのためには webpack-dev-middleware および HMR のために webpack-hot-middleware を使います。
今回はその設定手順をメモ。
公式ドキュメント
Webpack v1: https://webpack.github.io/docs/webpack-dev-middleware.html
Webpack v2: https://webpack.js.org/guides/development/#webpack-dev-middleware
設定手順
パッケージをインストールする
$ npm install -D webpack-dev-middleware webpack-hot-middleware
webpack.config.js を修正する
以下のように2箇所修正します。(ES2015 で書いてます)
// webpack.config.dev.babel.js import webpack from 'webpack'; export default { entry: [ + 'webpack-hot-middleware/client', './index', ], // Configuration for dev server devServer: { contentBase: path.resolve(path.join(__dirname, 'public')), port: 3000, }, devtool: 'cheap-module-eval-source-map', plugins: [ ... + new webpack.HotModuleReplacementPlugin(), ], });
Express アプリ内で middleware を読み込む
続いて、Express アプリ(ここでは server.js
)内で上述した2つの middleware を使用します。
(サーバーサイドも ES2015 で書いてる想定です)
// server.js import express from 'express'; import path from 'path'; const app = express(); const port = process.env.PORT || 8080; +if (process.env.NODE_ENV !== 'production') { + const webpack = require('webpack'); + const webpackDevMiddleware = require('webpack-dev-middleware'); + const webpackHotMiddleware = require('webpack-hot-middleware'); + const config = require('./webpack.config.dev.babel').default; + const compiler = webpack(config); + + app.use(webpackHotMiddleware(compiler)); + app.use(webpackDevMiddleware(compiler, { + noInfo: true, + publicPath: config.output.publicPath, + })); +} // Serve static files app.use(express.static(path.join(__dirname, 'public'))); console.log(`Served: http://localhost:${port}`); app.listen(port, (err) => { if (err) { console.error(err); } else { console.info(`==> 🌎 Listening on port ${port}. Open up http://localhost:${port}/ in your browser.`); } });
基本的には webpack の config ファイルを読み込んで一度 webpack()
に渡した後、それ(compiler
)をそれぞれの middleware に引数として渡してあげればよいです。
また、webpackDevMiddleware の第二引数に渡しているオプションは
noInfo
:info レベルのログを console に出力するかどうか。true
(しない)にしてる人が多い印象publicPath
(必須): webpack.config.js のoutput.publicPath
を指定しておけば OK
それ以外のオプションについては README を参照してください。
NOTE:
webpack.config を ES5 で書いてる場合
const config = require('./webpack.config.dev.babel').default;
の
.default
は不要です。
また、これらの middleware は本番環境では無効にしておく必要があるため
process.env.NODE_ENV
で切り替えができるようにしておきます。
サーバーを起動する
設定は以上です。後は package.json に
"scripts": { "start": "babel-node server.js" }
などと書き、
$ npm start
でサーバーを起動すると webpack-dev-server および HMR が有効になります。
注意事項
ここまでで開発時の設定としては十分なのですが、この webpack.config.js で本番環境用にビルドをすると
entry
や plugins
に HMR が含まれているため実行時にエラーになります。
GET http://localhost:8080/__webpack_hmr 404 (Not Found)
そのため、実際には開発用(dev server 用)と本番環境向けビルド用に config ファイルを分けるか、または条件分岐を行う必要があります。
このあたりはサンプルコードを作ったので参考にしてください。
config ファイルを
- webpack.config.base.babel.js:開発用でも本番環境用でも共通の設定
- webpack.config.dev.babel.js:開発用の設定(↑で挙げたような)を記載
- webpack.config.prod.babel.js:本番環境用の設定(圧縮など)を記載
というように3つに分割し、webpack-merge を使って base を残り2つにマージする形でそれぞれの環境用の config を生成しています。