前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。
https://www.captainbed.cn/ccc
在单页面应用(SPA)复杂度日益增长的今天,一个未经优化的Webpack构建产物可能面临:
Webpack的分包(Code Splitting)与合包(Chunk Merging)技术,正是解决这些痛点的核心方案。本文将深入剖析其工作原理,并提供生产级优化策略。
Webpack构建过程分为三个阶段:
类型 | 说明 | 示例 |
---|---|---|
Entry Chunk | 配置的入口文件生成 | main.js, app.js |
Child Chunk | 通过代码分割生成的子块 | src_Login_js.js |
Vendor Chunk | 第三方模块集合 | vendors~main.js |
Common Chunk | 多个入口共享的公共模块 | commonmainapp.js |
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000, // 最小分包体积
maxAsyncRequests: 5, // 最大异步请求数
maxInitialRequests: 3, // 最大初始请求数
automaticNameDelimiter: '~',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
// 动态导入实现路由级分包
const Login = () => import(/* webpackChunkName: "login" */ './views/Login.vue');
const Dashboard = () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue');
cacheGroups: {
react: {
test: /[\\/]node_modules[\\/](react|react-dom|react-router)/,
name: 'react-bundle',
chunks: 'all',
enforce: true
},
lodash: {
test: /[\\/]node_modules[\\/]lodash-es[\\/]/,
name: 'lodash',
chunks: 'all'
}
}
config.optimization.runtimeChunk = {
name: entrypoint => `runtime-${entrypoint.name}`
};
cacheGroups: {
core: {
test: ({ resource }) => (
resource &&
resource.includes('src/core') &&
!resource.includes('test')
),
name: 'core-commons',
chunks: 'initial',
minChunks: 1,
enforce: true
},
shared: {
test: /[\\/]src[\\/]shared[\\/]/,
name: 'shared-modules',
chunks: 'all',
minChunks: 3,
reuseExistingChunk: true
}
}
总加载时间 = 网络请求时间 * 文件数量 + 解析执行时间 * 文件体积
需找到文件数量和单个文件体积的最优平衡点
# 安装分析插件
npm install --save-dev webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
reportFilename: 'bundle-report.html'
})
]
};
output: {
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].chunk.js',
},
optimization: {
moduleIds: 'deterministic',
chunkIds: 'deterministic'
}
import(/* webpackPrefetch: true */ './components/Modal');
import(/* webpackPreload: true */ 'critical-module');
指令类型 | 加载优先级 | 适用场景 |
---|---|---|
prefetch | 低(空闲时) | 后续页面可能需要的资源 |
preload | 高(立即) | 关键路径资源 |
// webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
compress: {
layers: true // 启用分层优化
}
}
})
]
}
};
// 合并小文件请求
cacheGroups: {
http2: {
test: module => {
return module.size() < 1024 * 30 &&
module.nameForCondition().startsWith('src/components');
},
name: 'http2-bundle',
chunks: 'all',
minSize: 0,
minChunks: 3
}
}
const shouldLoadPolyfill = !supportsModernBrowser();
if (shouldLoadPolyfill) {
import(/* webpackChunkName: "polyfill" */ 'core-js/stable')
.then(() => import('regenerator-runtime/runtime'));
}
指标名称 | 健康阈值 | 测量工具 |
---|---|---|
首屏JS体积 | <200KB | Webpack Stats |
最大Chunk体积 | <500KB | Bundle Analyzer |
缓存命中率 | >85% | Lighthouse |
动态加载时间 | <1s (3G网络) | Chrome DevTools |
// 构建性能追踪
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap({
// webpack配置
});
// 上传分析数据到监控平台
const { WebpackMonitor } = require('webpack-monitor');
config.plugins.push(
new WebpackMonitor({
capture: true,
launch: true,
port: 3030
})
);
function getSplitChunksConfig(env) {
const isProd = env === 'production';
return {
chunks: 'all',
minSize: isProd ? 30000 : 10000,
maxAsyncRequests: isProd ? 5 : 20,
// 其他环境相关配置...
};
}
// 主应用配置
externals: {
'shared-deps': 'SharedDeps'
}
// 子应用配置
plugins: [
new webpack.container.ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Widget': './src/Widget.js'
},
shared: ['react', 'react-dom']
})
]
// 按地域动态加载SDK
const region = getUserRegion();
import(`@cloud-sdk/${region}/core`)
.then(sdk => sdk.init());
Webpack的分包与合包不是简单的配置调优,而是需要结合业务场景、技术架构和性能目标的系统工程。本文提出的策略已在多个千万级PV项目中验证,建议开发团队: