热更新
上文提到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`)
})