webpack으로 번들링된 React 파일 hot deployment로 개발 빠르게 하기

개요

server 모듈은 nodemon으로 hot deployment가 쉽게 가능하지만, client 모듈은 추가 설정을 해주어야 한다.\
webpack-dev-server로 이용해서도 쉽게 가능하지만, React를 SSR로 연동한 이상, webpack-dev-server보다는 아래의 방법으로 하는것이 더 효과적이다.

선행과정

express로 SSR이 구현되어 있어야 한다.

설치

npm i -D webpack-dev-middleware

webpack-dev-middleware

express에서만 사용할 수 있는 개발용 미들웨어 있다. webpack으로 부터 번들링된 파일들일 사용할 수 있게 도와준다.

webpack-hot-middleware

webpack-dev-middleware와 항상 같이 쓰이고, webpack-dev-server 없이 hot reloading을 할 수 있도록 도와준다.

구현

webpack.client.js

  1. plugins에 wepback.HotModuleReplacementPlugin 을 추가한다.
  2. entry array에 webpack-hot-middleware/client를 추가한다.
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const hotMiddlewareScript = `webpack-hot-middleware/client?path=/__webpack_hmr&timeout=200&reload=true`
const webpack = require('webpack')

module.exports = {
  entry: [hotMiddlewareScript, './src/client/index.js'],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, './dist'),
  },
  mode: 'development',
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/env', '@babel/preset-react'],
            plugins: ['@babel/plugin-proposal-class-properties'],
          },
        },
      },
    ],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: 'src/index.html',
    }),
  ],
}

server.js

webpack config 파일을 로드하고, webpack-dev-middleware와 webpack-hot-middleware를 추가한다.

import http from 'http'
import express from 'express'
import path from 'path'
import fs from 'fs'

const app = express()

const webpack = require('webpack')
const webpackConfig = require('../../webpack.client.js')

const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')

const compiler = webpack(webpackConfig)

app.use(webpackDevMiddleware(compiler))
app.use(webpackHotMiddleware(compiler))

const index = fs
  .readFileSync(path.resolve(__dirname, '../dist/index.html'))
  .toString()

app.use('/', express.static(path.resolve(__dirname, '../dist')))
app.get('*', (req, res) => {
  res.send(index)
})

const server = new http.Server(app)
server.listen(3000, (err) => {
  if (err) {
    return console.error(err)
  }
})