Webpack系列-热更新 webpack-dev-server

1,904 阅读2分钟

热更新

上文提到webpack的文件监听,它有两个主要的问题:

  • 需要手动刷新浏览器;
  • watch是监控磁盘文件的变化,生成的也是磁盘文件,构建速度慢。

解决方案就是使用 webpack-dev-server 和webpack自带的 HotModuleReplacementPlugin 插件配合实现热替换。

模块热替换-HotModuleReplacementPlugin

我觉得官网对热模块的解释最简单易懂,直接贴出来吧。

特性

模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:

  • 保留在完全重新加载页面时丢失的应用程序状态。
  • 只更新变更内容,以节省宝贵的开发时间。
  • 调整样式更加快速 - 几乎相当于在浏览器调试器中更改样式。

启用

plugins: [
    new webpack.HotModuleReplacementPlugin({
        // Options...
    })
]

webpack-dev-server

webpack-dev-server 提供了一个简单的web服务器,并且能够实时重新加载(live reloading)。但却是整个页面的刷新,所以需要和模块热替换插件配合使用。

webpack-dev-server 没有磁盘io,它的生成文件存在内存中,不像watch会生成磁盘文件(之前watch命令执行后output文件都会发生变化)。相比构建速度上webpack-dev-server更有优势。

webpack-dev-server 其实是基于 webpack-dev-middleware 和 Express 实现的,而 webpack-dev-middleware 其实是 Expressjs 的一个中间件。

启用HMR

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
    mode: 'development',
    entry: {
        app: './src/index.js'
    },
    devtool: 'inline-source-map',
    devServer: {
    contentBase: './dist',
        hot: true
        },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
            title: '热更新'
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ],
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
}

通过 Node.js API

当使用 webpack dev server 和 Node.js API 时,不要将 dev server 选项放在 webpack 配置对象(webpack config object)中。而是,在创建选项时,将其作为第二个参数传递。例如:

new WebpackDevServer(compiler, options)

想要启用 HMR,还需要修改 webpack 配置对象,使其包含 HMR 入口起点。webpack-dev-server package 中具有一个叫做 addDevServerEntrypoints 的方法,你可以通过使用这个方法来实现。

示例:

const webpack = require('webpack')
const webpackDevServer = require('webpack-dev-server')
const webpackDevConfig = require('./webpack.dev.config')


const port = 5000
const options = {
    contentBase: path.join(__dirname, '../dist'),
    host: '0.0.0.0',
    stats: { colors: true },
    hot: true,
    noInfo: false
}
webpackDevServer.addDevServerEntrypoints(webpackDevConfig, options)
const compiler = webpack(webpackConfig)
const server = new webpackDevServer(compiler, options)

server.listen(port, '0.0.0.0', function(err) {
    if (err) {
        console.error(err)
    }
    console.log('\n-------------\n')
    console.log(`http://127.0.0.1:${port}/index.html`)
})