面试题答案
一键面试实现开发、测试和生产环境不同配置
- 创建不同配置文件
在项目根目录下创建
webpack.dev.js
、webpack.test.js
、webpack.prod.js
分别对应开发、测试、生产环境配置。 例如webpack.dev.js
:
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
// 其他开发环境特有配置
};
webpack.prod.js
:
const path = require('path');
const MiniCssExtractPlugin = require('mini - css - extract - plugin');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.[contenthash].js'
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css - loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles.[contenthash].css'
})
],
// 其他生产环境特有配置
};
- 使用
webpack - merge
合并配置 安装webpack - merge
:npm install webpack - merge - - save - dev
。 在package.json
中配置脚本:
{
"scripts": {
"dev": "webpack - - config webpack.dev.js",
"test": "webpack - - config webpack.test.js",
"build": "webpack - - config webpack.prod.js"
}
}
例如可以创建一个webpack.common.js
存放公共配置,然后在各环境配置文件中使用webpack - merge
合并:
const merge = require('webpack - merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
// 开发环境特有配置
});
Webpack热更新(HMR)原理
- 总体流程
- 构建阶段:Webpack在开发模式下构建打包时,会将HMR相关代码注入到bundle中。
- 运行时:
- 客户端:浏览器端运行的HMR runtime会与Webpack dev server建立WebSocket连接,用于接收文件变化通知。
- 服务端:Webpack dev server监测到文件变化后,会重新编译模块,然后通过WebSocket向客户端发送更新消息。
- 模块热替换:客户端HMR runtime接收到更新消息,会请求更新的模块,然后尝试将新模块替换掉旧模块,而不刷新整个页面,实现局部更新。
- 模块热替换细节
- Webpack会为每个模块添加一个唯一的标识符(id),当模块发生变化时,新模块会有新的标识符。
- HMR runtime通过对比新旧模块的标识符,来判断哪些模块需要更新。对于支持HMR的模块,会调用模块自身的
module.hot.accept
回调函数(如果有)来处理更新逻辑,如更新DOM等;对于不支持HMR的模块,则会递归地卸载其依赖模块,并重新加载新模块。
在基于Webpack CLI搭建的项目中配置和使用HMR
- 开发环境配置中启用HMR
在
webpack.dev.js
中添加:
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
devServer: {
contentBase: path.join(__dirname, 'dist'),
hot: true
},
// 其他配置
};
- 在模块中使用HMR
对于JavaScript模块,例如
src/index.js
:
if (module.hot) {
module.hot.accept('./otherModule.js', function () {
// 当otherModule.js更新时执行的逻辑
console.log('otherModule.js has been updated!');
});
}
对于CSS模块,Webpack的style - loader
默认支持HMR,无需额外配置。当CSS文件更新时,style - loader
会自动更新页面中的样式。