背景
Webpack 是现代化前端项目的构建工具,它可以将各种资源打包成浏览器可识别的模块,提高前端项目的可维护性和性能。其中,热更新是一种非常实用的特性,可以在代码修改后自动更新浏览器页面,提高前端开发效率。
热更新的原理
热更新是指在代码保存后,自动更新页面,而不需要手动刷新浏览器。它的原理是通过 WebSocket 技术,在页面和开发服务器之间建立实时通信的连接,然后将代码变化实时通知给浏览器端。
前置条件
在实现热更新之前,需要确保你已经安装了 Webpack 以及相应的 loader 和插件,建议使用最新版本的 Webpack。
配置步骤
1. 添加 webpack-dev-server
webpack-dev-server 是一个基于 Express 的开发服务器,可以在本地启动服务,类似于 Node.js 的 http-server。它会将所有文件打包,然后将它们放到内存中,以便在修改时快速重载。
你可以通过 NPM 安装 webpack-dev-server:
npm install webpack-dev-server --save-dev
接下来在 Webpack 配置文件中添加以下代码:
// www.javascriptcn.com code example
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
contentBase: './dist',
hot: true, // 启用热更新
},
};其中,contentBase 是指示从哪个目录提供静态文件的选项,这里设置为 ./dist,表示在访问根目录时,会从 ./dist 目录中提供文件。hot 是指示是否启用热更新的选项。
2. 添加 webpack-hot-middleware
webpack-hot-middleware 是一个与 webpack-dev-server 配套的中间件,它可以在浏览器端和 webpack-dev-server 之间建立 WebSocket 连接,实现热更新功能。
在 Webpack 配置文件中添加以下代码:
// www.javascriptcn.com code example
const webpack = require('webpack');
const middleware = require('webpack-hot-middleware');
module.exports = {
// ...
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
contentBase: './dist',
hot: true,
// 添加 middleware
before(app) {
app.use(middleware(compiler));
},
},
};其中,webpack.HotModuleReplacementPlugin() 是 Webpack 内置的插件,用于启动模块热更新,并且它在 mode 为 development 时是默认启用的。before 是一个 devServer 的钩子,它会在建立连接前运行一些自定义代码,这里我们把 webpack-hot-middleware 加到 devServer 的前面。
3. 配置 React
如果你正在使用 React,你还需要添加 react-hot-loader,这是一个与 React 配套的热更新插件。
安装 react-hot-loader:
npm install react-hot-loader --save-dev
然后在 Webpack 配置文件中添加以下代码:
// www.javascriptcn.com code example
const webpack = require('webpack');
const middleware = require('webpack-hot-middleware');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
// ...
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ReactRefreshWebpackPlugin(),
],
devServer: {
contentBase: './dist',
hot: true,
// 添加 middleware
before(app) {
app.use(middleware(compiler));
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: [
'react-hot-loader/babel',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
],
},
},
},
],
},
resolve: {
alias: {
'react-dom': '@hot-loader/react-dom',
},
},
};其中,ReactRefreshWebpackPlugin 是一个与 React 配套的热更新插件。我们也要修改 babel-loader 配置,添加 react-hot-loader 插件。最后,我们还需要修改 react-dom 的引入方式,改成 @hot-loader/react-dom,这样才能启用热更新。
示例代码
以下是一个完整的 Webpack 配置文件,它可以配置 React 和热更新:
// www.javascriptcn.com code example
const path = require('path');
const webpack = require('webpack');
const middleware = require('webpack-hot-middleware');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const isDevelopment = process.env.NODE_ENV !== 'production';
const plugins = [
new webpack.HotModuleReplacementPlugin(),
];
if (isDevelopment) {
plugins.push(new ReactRefreshWebpackPlugin());
}
module.exports = {
mode: isDevelopment ? 'development' : 'production',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
contentBase: './dist',
hot: true,
// 添加 middleware
before(app) {
app.use(middleware(compiler));
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: isDevelopment ? [
'react-hot-loader/babel',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread',
] : [],
},
},
},
],
},
resolve: {
alias: {
'react-dom': isDevelopment ? '@hot-loader/react-dom' : 'react-dom',
},
},
plugins,
optimization: {
minimize: !isDevelopment,
},
};使用注意事项
在使用热更新功能时,建议将
mode设置为开发模式,这样可以避免一些不必要的错误。如果你的 React 组件不需要热更新,你可以改用
react-hot-loader提供的条件式热更新,只在需要时才进行更新,这样可以提高性能。开启热更新时,还需要在 React 组件中添加一个
AppContainer组件,用于包裹根组件并进行热更新。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d648e1a941bf7134bfc922