这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战
(一) webpack5之初体验
(二) webpack5之核心配置
(三) webpack5之生产配置
1,HTML代码压缩
webpack对开发和生产环境的配置是不一样的,默认情况下,生产环境的代码是压缩的,无需重新配置,只需要指定, mode = "production" , 但是,如果想要压缩HTML代码,需要添加配置
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true
}
}),
2,生产环境配置汇总
主要包括:
- css,less 等文件的兼容性处理,已经代码压缩
- 对html的处理和压缩
- 对图片和其他资源的处理
- 对eslint语法的配置
const { resolve } = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
process.env.NODE_ENV = 'production'
// 复用loader
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('postcss-preset-env')()
]
}
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/bundle.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: { version: 3 },
targets: {
chrome: '60',
firefox: '50'
}
}
]
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false
}
},
{
test: /\.html$/,
laoder: 'html-loader'
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/bundle.css'
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeComments: true
}
})
],
mode: 'production'
};
3,webpack性能优化
1,开发环境性能优化
2,生产环境性能优化
(1) 开发环境性能优化的几个方面:
-
优化打包构建速度
- 优化代码调试
(2) 生产环境性能优化
- 优化打包构建速度
- 优化代码运行的性能
4,热模块替换
作用: 一个模块发生变化,只会重新打包这一个模块,而不是打包所有模块,极大提升构建速度,要开启HMR功能也是很简单的,只需要在devServer中配置hot: true
devServer: {
// 运行项目目录
contentBase: resolve(__dirname, 'build'),
// 启动压缩
compress: true,
// 端口号
port: 3000,
// 自动打开浏览器
open: true,
// 开启HMR功能
hot : true,
}
注意:
1,样式文件:可以使用HMR功能,因为style-laoder内部实现了
2,js文件,默认不能使用HMR功能, 需要修改JS代码,让其支持HMR功能, HMR功能对JS的处理,只能处理非入口JS文件的其他文件。
3, HTML文件:默认不能使用HMR功能,同时会导致问题,html文件不能热更新了
解决方案: 修改entry入口,将html文件引入
module.exports = {
entry: ['./src/index.js', './src/index.html'],
output: {
filename: 'js/bundle.js',
path: resolve(__dirname, 'build')
},
}
当然也可以单独配置某一块
if(module.hot) {
// 一旦module.hot为true,说明开启了HMR功能,
module.hot.accept('./uitls.js', function() {
// 会监听uitls.js文件的变化,一旦发生变化,其他默认不会重新打包构建
print()
})
}
4, webpack的热更新原理?
webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。
这个机制可以做到不用刷新浏览器而 将新变更的模块替换掉旧的模块 原理:
1,第一步:在 webpack 的 watch 模式下,文件系统中某一个文件发生修改,webpack 监听到文件变化,根据 配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中
2,第二步: webpack-dev-server 和 webpack 之间的接口交互,而在这一步,主要是 dev-server 的中间 件 webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware 调用 webpack 暴露 的 API对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
3,第三步: webpack-dev-server 对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打 包。当我们在配置文件中配置了devServer.watchContentBase 为 true 的时候,Server 会监听这些配置文 件夹中静态文件的变化,变化后会通知浏览器端对应用进行 live reload。注意,这儿是浏览器刷新,和 HMR 是两个概念。
4,第四步: 该步骤主要是通过在浏览器端和服务端之间建立一个 websocket 长连接,将 webpack 编译打包的各个阶段的状态信息告知浏 览器端,同时也包括第三步中 Server 监听静态文件变化的信息。浏览器端根据这些 socket 消息进行不同的操 作。当然服务端传递的最主要信息还是新模块的 hash 值,后面的步骤根据这一 hash 值来进行模块热替换。
5,第五步:webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交回 给了 webpack,webpack/hot/dev-server 的工作就是根据 webpack-dev-server/client 传给它的信息 以及 dev-server 的配置决定是刷新浏览器呢还是进行模块热更新。当然如果仅仅是刷新浏览器,也就没有后面那些步
6,第六步:HotModuleReplacement.runtime 是客户端 HMR 的中枢,它接收到上一步传递给他的新模块的 hash 值,它通过 JsonpMainTemplate.runtime 向 server 端发送 Ajax 请求,服务端返回一个 json,该 json 包 含了所有要更新的模块的 hash 值,获取到更新列表后,该模块再次通过 jsonp 请求,获取到最新的模块代码
7,第七步:在该步骤中,HotModulePlugin 将会对新旧模块进行对比,决 定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用
8,第八步:当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。
5,webpack解决性能问题
总结一下上面的生产配置:
1 ,压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和 ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
2,利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output 参数和各loader的publicPath参数来修改资源路径
3,删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数-- optimize-minimize来实现
4,提取公共代码。