webpack优化
1、优化产出代码
1、小图片使用base64编码
2、bundle加hash--[contenthash:8]
3、懒加载
4、提取公共代码
5、IgnorePlugin
6、使用cdn加速
7、使用production
8、使用scope hosting
2、优化打包构建
1、优化babel-loader(production)
babel编译es6->es5过程中消耗多
{
test: /\.js$/,
use: ['babel-loader?cacheDirectory'], // 开启缓存
include: path.reslove(__dirname, 'src'), // 明确范围
// exclude: path.reslove(__dirname, 'node-modules') // 排除范围
// include和exclude选择其一即可
}
2、ignorePlugin(production)
避免引入无用模块
plugin: [
...
// 忽略moment下面的/locale目录
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
]
3、noParse(production)
避免重复打包
module.export = {
module: {
rules: [...],
// 忽略对‘react.min.js’ 文件的递归解析处理
noParse: [/react\.min\.js$/]
}
}
IgnorePlugin vs noParse
IgnorePlugin直接不引入,代码中没有
noParse引入,但不打包
两者都优化打包体积
4、happyPack(production)
多进程打包工具
const HappyPack = require('happyPack');
module.export = {
module: {
rules: [
test: /\.js$/,
use: ['happypack/loader?id=babel']
]
},
plugin: {
new HappyPack({
id: 'babel', //唯一标识符,与上面对应
loaders: ['babel-loader?cacheDirectory']
})
}
}
5、ParallelUglifyPlugin(production)
多进程代码压缩
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin);
...
plugin: [
new ParallelUglifyPlugin({
uglify: {
output: {
beautify: false, // 最紧凑的输出
comments: false, // 删除所有注释
},
compress: {
drop_console: ture, // 删除console
collapse_var: true,
reduce_vars: true
}
}
})
]
happyPack、ParallelUglifyPlugin适合大型项目,小型会降低速度
6、自动刷新(development)
编译完成浏览器自动刷新
module.export = {
watch: true, // 开启监听
watchOption: {...} // 监听配置
}
7、热更新(development)
浏览器不用刷新代码就生效
自动刷新 vs 热更新
自动刷新:整个网页全部刷新,网速较慢,状态会丢失
热更新:新代码生效,网页不刷新,状态丢失
8、DLLPlugin(development)
提前将第三方库打包成DLL取引用
3、为何要打包构建
体积更小,加载更快
编译高级语言或语法(ts、es6+、模块化、sass等)
兼容性和错误检查(polyfill、postcss、eslint)
统一高效的开发环境、构建流程和产出标准
集成公司构建规范(提测、上线等)
4、module、chunk、bundle区别
module-各个源码文件,js css png等
chunk--分析过程中多个模块合并成的
bundle--最终输出的文件
module-->chunk-->bundle
5、基本配置
// webpack.config.js文件写入
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
mode: 'development',
entry: 'index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
},
plugins: [
new CleanWebpackPlugin(), // 在打包前删除所有上一次打包好的文件
new HtmlWebpackPlugin({
template: 'src/index.html'
})
],
module: {
rules: [
{
test: /\.(js|ts)$/,
loader: 'babel-loader',
include: /src/,
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: '[name]_[hash].[ext]', // 打包名称 name-原始名称, hash使用md5算法,ext是后缀
outputPath: 'images/',
limit: 5*1024 // 小于5kb的图片用base64格式产出,否则沿用file-loader产出url格式
}
},
{
test: /\.css$/,
use: ['style-loader','css-loader', 'postcss-loader']
},
{
test: /\.sass$/,
use: ['style-loader', 'css-loader', 'sass-loader', 'postcss-loader']
}
]
}
}
6、压缩抽离css、公共代码、js
// webpack.pro.js
const path = require('path');
const WebpackCommonConf = require('./webpack.common');
const { merge } = require('webpack-merge'); // merge合并WebpackCommonConf公共配置
const MiniCssExtractorPlugin = require('mini-css-extrator-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-plugin');
module.exports = merge(WebpackCommonConf, {
mode: 'production',
output: {
filename: '[name][contenthash:8].js',
path: path.join(__dirname, 'dist_pro')
},
plugins: [
// 抽离css
new MiniCssExtractorPlugin({
filename: '[name][contenthash:8].css'
})
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractorPlugin.loader, // 生产环境由‘style-loader’换为 MiniCssExtractPlugin.loader
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
MiniCssExtractorPlugin.loader,
'css-loader',
'less-loader',
'postcss-loader'
]
}
]
},
optimization: {
// 压缩css
minimizer: [ new TerserJSPlugin(), new OptimizeCssAssetsPlugin() ],
// 分割代码块
splitChunks: {
chunks: 'all',
/*
* initial 入口chunk,对异步导入的文件不处理
* async 异步chunk,只对异步导入的文件处理
* all 全部chunk
* */
// 缓存分组
cacheGroups: {
// 第三方模块
vendor: {
name: 'vendor', // chunk名称
priority: 1, // 权重更高,优先抽离
test: /node-modules/,
minSize: 0, // 大小限制
minChunk: 1 // 最少复用过几次
},
// 公共模块
common: {
name: 'common',
priority: 0,
minSize: 0,
minChunk: 2
}
}
}
}
})
webpack和vite对比
- 1.开发模式不同
Webpack在开发模式下依然会对所有模块进行打包操作,虽然提供了热更新,但大型项目中依然可能会出现启动和编译缓慢的问题;而Vite则采用了基于ES Module的开发服务器,只有在需要时才会编译对应的模块,大幅度提升了开发环境的响应速度。
- 2.打包效率不同
Webpack在打包时,会把所有的模块打包成一个bundle,这会导致初次加载速度较慢;而Vite则利用了浏览器对ES Module的原生支持,只打包和缓存实际改动的模块,从而极大提高了打包效率。
- 3.插件生态不同
Webpack的插件生态非常丰富,有大量社区和官方插件可以选择,覆盖了前端开发的各个方面;而Vite的插件生态尽管在不断发展,但相比Webpack来说还显得较为稀少。
- 4.热更新机制不同
Webpack的热更新需要整个模块链重新打包和替换,对于大型项目可能会有延迟;Vite的热更新则只会针对改动的模块进行更新,提高了更新速度。
- 5.应用场景不同
webpack由于其丰富的功能和扩展性,适合于大型、复杂的项目。而vite凭借其轻量和速度,更适合于中小型项目和快速原型开发。
vite比webpack快的原因
-
利用了浏览器对 ESM 的原生支持
Vite 利用了现代浏览器对 ES Modules(ESM)的原生支持,这使得在开发环境下,Vite 可以直接运行源代码,而无需像 Webpack 那样先进行打包。由于省去了打包的过程,Vite 的启动速度非常快。相比之下,Webpack 需要将源代码打包成浏览器可识别的格式,这个过程会消耗一定的时间。
-
按需编译
Vite 采用了按需编译的策略,只有当请求某个模块时,才会对该模块进行编译。这种按需加载的方式极大地缩减了编译时间。而 Webpack 在构建时会对整个项目进行扫描和分析,无论模块是否被使用,都会被打包进最终的输出文件中,这会增加构建的时间。
-
采用了不同的构建机制
Webpack 是基于 Node.js 实现的,而 Vite 是使用 Esbuild 预构建依赖。Esbuild 是一个使用 Go 语言编写的打包工具,其构建速度比以 Node.js 编写的打包器要快得多。这是因为 Go 语言在编译和执行速度上具有优势,使得 Esbuild 能够更快速地完成依赖的预构建。
前端重新部署如何通知浏览器刷新
可以结合使用Service Worker和WebSocket来实现更高效的通知机制;
同时,也可以在后端配合设置版本号接口和HTTP响应头来控制缓存(如Cache-Control或ETag)和版本更新