模块化
Webpack
入口entry
分离app和第三方库入口
这是什么? 这是告诉 webpack 我们想要配置 2 个单独的入口点(例如上面的示例)。
为什么? 这样你就可以在 vendor.js 中存入未做修改的必要 library 或文件(例如 Bootstrap, jQuery, 图片等),然后将它们打包在一起成为单独的 chunk。内容哈希保持不变,这使浏览器可以独立地缓存它们
,从而减少了加载时间。
多页面
这是什么? 我们告诉 webpack 需要三个独立分离的依赖图(如上面的示例)。
为什么? 在多页面应用程序中,server 会拉取一个新的 HTML 文档给你的客户端
。页面重新加载此新文档,并且资源被重新下载。然而,这给了我们特殊的机会去做很多事,例如使用 optimization.splitChunks 为页面间共享的应用程序代码创建 bundle
。由于入口起点数量的增多,多页应用能够复用多个入口起点之间的大量代码/模块
,从而可以极大地从这些技术中受益。
输出 output
loader
loader:webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
loader 用于转换某些类型的模块,而插件plugin则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量
。
常用的js处理babel-loader、样式处理css-loader、style-loader、文件file-loader、url-loader(小base64,大前)
自定义
plugin
打包优化
、资源管理
和环境注入
常见plugin:
老版本webpack插件:
代码优化plugin:
mini-css-estract-plugin(提取)、compression-webpack-plugin(压缩文件)、terser-webpack-plugin(压缩js代码)、cssMinizer(压缩css)、split-chunk-plugin(分割)
性能优化手段
代码分割
Webpack代码分割原则与最佳实践
一、文件分割阈值
建议对以下类型文件进行分割:
- 第三方依赖库:体积超过 50 K B 50KB 50KB(如React全家桶、Ant Design)
- 业务代码模块:超过 100 K B 100KB 100KB的独立功能模块
- 公共资源:复用率>3次的公共组件/工具类
二、核心分割原则
1. 按业务维度拆分
// 路由级动态导入(React示例)
const Dashboard = React.lazy(() => import('./views/Dashboard'));
2. 第三方库独立打包
// webpack.config.js
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: 10
}
}
}
}
3. 动态加载优化
// 带加载状态的动态导入
const Editor = lazy(() => import(/* webpackPrefetch: true */ './Editor').then(module => ({
default: module.Editor
})));
三、性能平衡策略
首屏关键资源
:$ \text{总大小} \leq 200KB $非关键资源延迟加载
:使用webpackPreload
和webpackPrefetch
缓存优化
:配置contenthash
output: {
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js'
}
四、监控与调优
- 使用
webpack-bundle-analyzer
分析模块分布 - 通过Chrome DevTools的Coverage工具检测利用率
设置报警阈值
:- 单个chunk超过 500 K B 500KB 500KB时告警
- 未使用的代码超过 30 % 30\% 30%时优化
最佳实践示例配置:
// webpack.prod.js
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 200000,
cacheGroups: {
charts: {
test: /[\\/]node_modules[\\/](echarts|d3)/,
priority: 20
},
utils: {
test: /[\\/]src[\\/]utils/,
minChunks: 3
}
}
}
}
注意事项:
- HTTP/2环境下可适当放宽单文件大小限制
- 移动端优先项目建议更严格的体积控制
- 长期缓存策略需配合CDN版本管理### Webpack代码分割原则与最佳实践
压缩
TreeShaking
核心原理
Tree Shaking是基于ES Module
静态语法分析的代码优化技术,通过识别模块导入/导出关系
,消除未被使用的代码(dead code)
。其有效性依赖以下条件:
- 模块必须使用ES6的
import/export
语法 - 代码
不应产生副作用
(无全局变量修改等) - 构建工具需进行
依赖关系分析
Webpack配置步骤
- 基础配置
// webpack.config.js
module.exports = {
mode: 'production', // 自动启用优化
optimization: {
usedExports: true, // 标记被使用导出
minimize: true, // 启用代码压缩
minimizer: [new TerserPlugin()] // 使用压缩工具
}
}
- package.json配置
{
"sideEffects": [
"*.css", // 标记有副作用的文件
"*.global.js"
]
}
- Babel配置注意项
// .babelrc
{
"presets": [
["@babel/preset-env", {
"modules": false // 保留ES模块语法
}]
]
}
代码规范要求
- 模块导出使用具名导出:
// math.js
export const square = x => x * x
export const cube = x => x * x * x
- 按需导入:
// app.js
import { square } from './math.js'
console.log(square(5))
高级优化策略
- 作用域提升(Scope Hoisting)
optimization: {
concatenateModules: true
}
- 第三方库优化配置:
// webpack.config.js
rules: [{
test: /\.js$/,
include: /node_modules\/lodash-es/,
use: 'babel-loader'
}]
常见问题排查
无效摇树检查清单:
- 检查
@babel/plugin-transform-modules-commonjs
是否被禁用 - 确认
sideEffects
配置是否正确 - 验证第三方库是否提供ES模块版本(如lodash-es)
- 检查
副作用代码示例:
// 会阻止Tree Shaking的写法
window.someGlobal = 'value' // 修改全局对象
import './polyfill' // 无导出但影响运行环境
效果评估指标
通过webpack-bundle-analyzer分析构建结果:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
module.exports = {
plugins: [new BundleAnalyzerPlugin()]
}