🌐

Dockerでwebpack-dev-server(HMR)の環境を構築・実行

3 min read

完成形のプロジェクト

https://github.com/asano-yuki/docker-webpack

1. バージョン情報

  • node:14.6.0
  • webpack:5.33.2

2. ファイル構成

.
├── front
    ├── public
    ├── src
        ├── app.js
        ├── index.html
        ├── index.js
    ├── npm.sh
    ├── package-lock.json
    ├── package.json
    ├── webpack.config.js    
├── docker-compose.yml

3. docker-compose.yml

コンテナ上でnpmを実行。
コマンド一つで環境を構築できるように、image と command も doker-compose.yml に記述。

コンテナの規模が大きくなるとHMRが正常に動作しない場合があるので、あらかじめポーリングを指定する(CHOKIDAR_USEPOLLING=true)。

./docker-compose.yml
version: '3'
services:
  front:
    image: node:14.16.0
    container_name: front
    working_dir: /usr/src/app
    tty: true
    environment: 
      - CHOKIDAR_USEPOLLING=true
    volumes:
      - ./front:/usr/src/app
    command: ./npm.sh
    ports:
      - "3000:3000"

4. package.json

./front/package.json
{
  "name": "front",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production",
    "watch:dev": "webpack --mode development --watch",
    "watch:build": "webpack --mode production --watch",
    "server": "webpack serve --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.13.15",
    "@babel/preset-env": "^7.13.15",
    "babel-loader": "^8.2.2",
    "html-webpack-plugin": "^5.3.1",
    "webpack": "^5.33.2",
    "webpack-cli": "^4.6.0",
    "webpack-dev-server": "^3.11.0"
  }
}

5. webpack.config.js

host: '0.0.0.0' を指定することで、コンテナ上で動作するローカルサーバーにアクセスできるようになる。また、同じネットワークに属する別端末からもアクセス可能。

webpack5 で target を複数指定(配列)した場合、HMRが正常に動作しない。対応策としては、mode に応じて target の値を切り替える。

webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = (env, args) => {
  return {
    mode: args.mode,
    entry: './src/index.js',
    output: {
      path: path.join(__dirname, 'public'),
      filename: 'index.js'      
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [
                  '@babel/preset-env'
                ]
              }
            }
          ]
        }
      ]
    },
    target: args.mode === 'development' ? 'web' : ['web', 'es5'],
    devServer: {
      contentBase: path.join(__dirname, 'public'),
      host: '0.0.0.0',
      port: 3000,
      hot: true,
      watchOptions: {
        aggregateTimeout: 600,
        poll: 1000
      },
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: path.join(__dirname, 'src', 'index.html')
      })
    ]
  }
}

Discussion

ログインするとコメントできます