Bundle size optimization
The Necessity of Bundle Size Optimization
Vue.js projects experience continuous bundle size growth as features are added. Excessively large bundles lead to slow first-screen loading, negatively impacting user experience. This is particularly critical for mobile devices or environments with poor network conditions. Analyzing reports generated by webpack-bundle-analyzer provides clear visibility into module distribution.
npm install --save-dev webpack-bundle-analyzer
// vue.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
configureWebpack: {
plugins: [new BundleAnalyzerPlugin()]
}
}
Code Splitting Strategies
Route-based Lazy Loading
Vue Router supports dynamic import syntax to split route components into separate chunks, loading them only when accessing corresponding routes.
const routes = [
{
path: '/dashboard',
component: () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue')
},
{
path: '/settings',
component: () => import(/* webpackChunkName: "settings" */ './views/Settings.vue')
}
]
Component-level Code Splitting
For large components, use dynamic imports with Vue's defineAsyncComponent
:
import { defineAsyncComponent } from 'vue'
const HeavyComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
)
Third-party Library Optimization
On-demand Component Library Import
UI libraries like Element Plus support selective importing:
import { ElButton, ElSelect } from 'element-plus'
// Configure auto-import in Vue projects
// vite.config.js
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
Lightweight Alternatives
Consider smaller alternatives:
- Date processing: day.js instead of moment.js
- HTTP client: axios instead of superagent
- Utility functions: lodash-es with babel-plugin-lodash for tree-shaking
Tree Shaking Configuration
Ensure proper Tree Shaking configuration:
// webpack.config.js
module.exports = {
optimization: {
usedExports: true,
minimize: true,
sideEffects: true
}
}
Add to package.json:
{
"sideEffects": [
"*.css",
"*.scss"
]
}
Image Resource Optimization
Image Compression
Use image-webpack-loader for automatic compression:
module.exports = {
chainWebpack: config => {
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
mozjpeg: { progressive: true, quality: 65 },
optipng: { enabled: false },
pngquant: { quality: [0.65, 0.9], speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
})
}
}
Modern Image Formats
Prioritize WebP format:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.tap(options => {
options.limit = 10240 // 10KB
options.fallback.options.name = 'img/[name].[hash:8].[ext]'
return options
})
}
}
Build Configuration Optimization
Disable Source Maps in Production
// vue.config.js
module.exports = {
productionSourceMap: false
}
Smart Chunk Splitting
// vue.config.js
module.exports = {
configureWebpack: {
optimization: {
splitChunks: {
chunks: 'all',
maxSize: 244 * 1024, // 244KB
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
}
}
Runtime Optimization
Server-side Gzip Compression
npm install compression-webpack-plugin --save-dev
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
configureWebpack: {
plugins: [
new CompressionPlugin({
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
})
]
}
}
Preload/Prefetch Optimization
<link rel="preload" href="/assets/important.js" as="script">
<link rel="prefetch" href="/assets/next-page.js" as="script">
Vue CLI automatic configuration:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugin('preload').tap(options => {
options[0] = {
rel: 'preload',
include: 'allAssets',
fileBlacklist: [/\.map$/, /hot-update\.js$/]
}
return options
})
}
}
Long-term Maintenance Strategy
Regular Bundle Analysis
Implement CI/CD bundle size checks:
npm install --save-dev size-limit
{
"scripts": {
"size": "size-limit",
"build": "vue-cli-service build && npm run size"
},
"size-limit": [
{
"path": "dist/js/chunk-vendors.*.js",
"limit": "300 KB"
},
{
"path": "dist/js/app.*.js",
"limit": "150 KB"
}
]
}
Dynamic Polyfill Service
Use polyfill.io for on-demand loading:
<script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2Ces2016%2Ces2017%2Ces2018%2Ces2019"></script>
Advanced Optimization Techniques
WebAssembly for Performance-critical Tasks
// Load WASM module
async function loadWasm() {
const imports = {}
const res = await fetch('module.wasm')
const bytes = await res.arrayBuffer()
const { instance } = await WebAssembly.instantiate(bytes, imports)
return instance.exports
}
// Usage
const wasmModule = await loadWasm()
const result = wasmModule.heavyCalculation(123)
SSR Optimization
Avoid duplicate bundles in SSR:
// Use webpack externals
module.exports = {
configureWebpack: {
externals: process.env.NODE_ENV === 'production' ? {
'vue': 'Vue',
'vue-router': 'VueRouter',
'axios': 'axios'
} : {}
}
}
Monitoring and Continuous Optimization
Implement performance monitoring:
// Record build stats
const { StatsWriterPlugin } = require('webpack-stats-plugin')
module.exports = {
configureWebpack: {
plugins: [
new StatsWriterPlugin({
filename: 'stats.json',
fields: ['assets', 'chunks', 'modules']
})
]
}
}
Configure CI systems with bundle size alerts to prevent accidental large dependency introductions.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn