阿里云主机折上折
  • 微信号
Current Site:Index > Bundle size optimization

Bundle size optimization

Author:Chuan Chen 阅读数:6504人阅读 分类: Vue.js

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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.