本文介绍如何在不依赖 React 的情况下,配置 Webpack 实现最简化的热模块替换(HMR)。通过结合 webpack-dev-server 与 nodemon 监听配置文件变化,演示如何配置 package.json 和 webpack.config.js,实现代码修改后无需刷新页面即可更新模块,适用于单一状态树的应用场景。
Webpack HMR 配置简介
本文介绍一种无需 React 等框架支持的 Webpack 热模块替换(HMR)极简配置方案,通常也被称为热更新。
模块热替换(HMR)的核心功能是在应用运行期间,无需刷新整个页面即可动态替换、添加或删除特定模块。这种机制对于由单一状态树构成的应用尤为有效,因为这类应用中的组件通常是“哑”组件(相对于“智能”组件),在代码变更后,组件状态仍能准确反映应用的最新状态。
Webpack-dev-server 内置了“实时重载”(live reload)功能,会在文件变更时自动刷新页面。
项目目录结构
项目文件目录结构如下:
- app
- a.js
- component.js
- index.js
- node_modules
- package.json
- webpack.config.js
模块导入与热更新原理
在 component.js 中导入 a.js,而在 index.js 中导入 component.js。只要修改其中任意一个文件,即可触发热更新功能。
核心代码配置
最关键的部分在于 index.js 中包含以下代码,这是实现热更新所必需的:
if(module.hot){
module.hot.accept(moduleId, callback);
}
package.json 配置详解
以下是 package.json 的配置内容:
{
"name": "webpack-hmr",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon --watch webpack.config.js --exec \"webpack-dev-server --env development\"",
"build": "webpack --env production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^2.28.0",
"nodemon": "^1.11.0",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.1"
}
}
从依赖列表可以看出,这是一个极其简单的配置。其中 nodemon 用于监听 webpack.config.js 文件的状态,一旦该文件发生变动,nodemon 会自动重新执行相关命令。
关于 html-webpack-plugin,在此配置中是可以省略的。具体配置细节请参考:https://www.npmjs.com/package/html-webpack-plugin 。
这里定义了两个命令:start 用于开发环境,build 用于生产环境。--watch 参数用于监听一个或多个文件,--exec 则是 nodemon 用来执行其他命令的标志。具体配置说明请参考:https://c9.io/remy/nodemon。
webpack.config.js 配置说明
接下来是 webpack.config.js 配置文件。既然在 package.json 的 scripts 中定义了两类命令,我们需要在配置文件中实现两种情况的处理(即 development 和 production,你也可以根据需要修改配置以只保留一种)。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const PATHS = {
app: path.join(__dirname, 'app'),
build: path.join(__dirname, 'build'),
};
const commonConfig={
entry: {
app: PATHS.app + '/index.js',
},
output: {
path: PATHS.build,
filename: '[name].js',
},
watch: true,
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack demo',
}),
],
}
function developmentConfig(){
const config ={
devServer:{
historyApiFallback:true, //404s fallback to ./index.html
// hotOnly:true, 使用hotOnly和hot都可以
hot: true,
stats:'errors-only', //只在发生错误时输出
// host:process.env.Host, 这里是undefined,参考的别人文章有这个
// port:process.env.PORT, 这里是undefined,参考的别人文章有这个
overlay:{ //当有编译错误或者警告的时候显示一个全屏overlay
errors:true,
warnings:true,
}
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // 更新组件时在控制台输出组件的路径而不是数字ID,用在开发模式
// new webpack.HashedModuleIdsPlugin(), // 用在生产模式
],
};
return Object.assign(
{},
commonConfig,
config,
{
plugins: commonConfig.plugins.concat(config.plugins),
}
);
}
module.exports = function(env){
console.log("env",env);
if(env=='development'){
return developmentConfig();
}
return commonConfig;
};
关于 Object.assign,其第一个参数为目标对象。如果目标对象中的属性具有相同的键,则该属性将被源对象中的属性覆盖。后续的源属性会类似地覆盖先前的属性。这是一种浅赋值操作,对于对象的复制使用 = 号,即引用复制。
env 参数通过命令行接口(CLI)传入。
运行与测试
然后打开命令行进入当前目录,运行 npm start 或 npm run build 即可。需要注意的是,前者仅在开发环境下运行,不会输出文件(文件存在于内存中),只有运行后者才会生成实际的输出文件。
Demo 代码位于:https://github.com/yuwanlin/webpackHMR
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。