webpack的模块热替换功能,简称HMR,允许在运行时更新各模块而无需对网页进行刷新。

webpack-dev-server中提供了模块热替换功能,只需要将hot属性设置为true即可使用。

只用于开发环境。

demo:

webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');

module.exports = {
  mode: 'development',
  entry: {
    app: "./src/index.js",
  },
  devtool: 'eval-source-map',
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    port: 9000,
    compress: true,
    // hot: true
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: '管理输出'
    }),
    new WebpackManifestPlugin()
  ],
  output: {
    filename: "[name].bundle.js",
    path: path.resolve(__dirname, "dist"),
    publicPath: '/'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(png|svg|jpe?g|gif)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 35840,
              name: '[name]_[hash:7].[ext]',
              outputPath: '/images/',
              publicPath: 'images/'
            }
          },
        ],
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'url-loader'
        ]
      }
    ],
  },
};

index.js

import _ from 'loadsh';
import './style.css'
import Icon from './image/icon.png';
import printMe from './print'

function component() {
    let element = document.createElement('div');
    let btn = document.createElement('button');
  
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');

    btn.innerHTML = 'printMe';
    btn.onclick = printMe;
    element.appendChild(btn)

    return element;
}
  
document.body.appendChild(component());

print.js

export default function printMe() {
    let appendDiv = document.createElement('div');
    appendDiv.classList.add('divStyle')
    document.body.appendChild(appendDiv)
}

style.css

@font-face {
    font-family: 'GraublauWeb';
    src: url('./font/GraublauWeb.woff.ttf');
    font-weight: 400;
    font-style: normal;
}
.hello {
    font-size: 36px;
    color: green;
    font-family: 'GraublauWeb'; 
    background: url('./image/icon.png');
}

.imageStyle {
    display: block;
    width: 50px;
    height: 50px;
}
.divStyle {
    width: 100px;
    height: 100px;
    margin: 10px;
    background: yellow;
}

package.json

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "watch": "webpack --watch",
    "start": "webpack-dev-server --open",
    "build": "npx webpack --config webpack.config.js",
    "server": "node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^4.5.2",
    "loadsh": "0.0.4",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.2"
  },
  "devDependencies": {
    "clean-webpack-plugin": "^4.0.0-alpha.0",
    "css-loader": "^5.2.4",
    "express": "^4.17.1",
    "image-webpack-loader": "^6.0.0",
    "style-loader": "^2.0.0",
    "url-loader": "^4.1.1",
    "webpack-dev-middleware": "^4.1.0",
    "webpack-dev-server": "^3.11.2",
    "webpack-manifest-plugin": "^3.1.1",
    "webpack-nano": "^1.1.1"
  }
}

当我们执行npm run start时,会打开localhost:9000的网址,并且每点击一次按钮会出现一个div

但是当我们去修改.divStyle的background属性时,就会引起浏览器的刷新,导致这些通过点击生成的div就会消失。

但是如果开始webpack-dev-server的hot属性,就可以保证在修改css时不会引起浏览器的刷新,这样动态生成的div就不会消失。