Skip to content

手动分包

手动分包,可以减少打包时间,减少打包体积,减少打包后的文件大小,提高打包速度。

以下是分包前 vite.config.js 的代码

javascript
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

此时打包后的文件大小为 3.5MB,即使在 grip 压缩后仍有 1 MB 左右。 打包耗时约 23 秒。

于是对 vite.config.js 进行优化,手动分包。

javascript
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build:{
    rollupOptions: {
      output: {
        manualChunks: {
          // 只保留第三方库的分包
          'vendor': ['vue', 'vue-router', 'pinia', 'ant-design-vue'],
          'utils': ['axios', 'lodash']
        }
      }
    },
    chunkSizeWarningLimit: 1000,
  },
})

此时打包后的文件大小为 1.99 MB,即使在 grip 压缩后仍有 0.529 MB 左右。 打包耗时约 16 秒。

自动导入插件 unplugin-vue-components

在手动分包的基础上,采用 unplugin-vue-components 插件,可以进一步减少打包体积,提高打包速度。

首先安装 unplugin-vue-components

bash
npm install unplugin-vue-components -D

因为 ant-design-vue 的样式文件默认是 less 格式的,因此还需额外配置样式处理器

javascript
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';

export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [
        AntDesignVueResolver({
          importStyle: 'less',
          resolveIcons: true,
        }),
      ],
    }),
  ],
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
      },
    },
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build:{
    rollupOptions: {
      output: {
        manualChunks: {
          // 只保留第三方库的分包
          'vendor': ['vue', 'vue-router', 'pinia', 'ant-design-vue'],
          'utils': ['axios', 'lodash']
        }
      }
    },
    chunkSizeWarningLimit: 1500,
  },
})

使用了按需导入插件之后,那么就需要 main.js 中取消全局导入(最基本的样式还是要全局导入)

javascript
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import { createPersistedState } from 'pinia-plugin-persistedstate';
import App from './App.vue';
import router from './router';
// 只对样式进行全局导入
import 'ant-design-vue/dist/reset.css';

const app = createApp(App);
const pinia = createPinia();

// 使用持久化插件
pinia.use(createPersistedState());

app.use(pinia);
app.use(router);
app.mount('#app');

此时对比刚开始的打包文件大小,原始文件总体积减少了 1.269 MB 左右。 此时原始文件约为1258.66 kB, 压缩体积为 390.17 kB

在此基础上,继续优化,使用公共 CDN 加速

使用了 字节 CDN,并配置多个 CDN 源备用

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>招投标平台</title>
    
    <!-- CDN 错误处理 -->
    <script>
      window.CDN_FAILED = false;
      function loadBackupCDN(lib) {
        if (window.CDN_FAILED) return;
        console.warn(`失败`);
        window.CDN_FAILED = true;
      }
    </script>
    
    <!-- 主要 CDN - 字节 -->
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/3.3.4/vue.global.prod.min.js" 
            onerror="loadBackupCDN('vue')"></script>
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue-router/4.2.4/vue-router.global.prod.min.js"
            onerror="loadBackupCDN('vue-router')"></script>
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/pinia/2.1.6/pinia.iife.prod.min.js"
            onerror="loadBackupCDN('pinia')"></script>
     <!-- 备用 CDN - 七牛云 -->
     <script defer src="https://cdn.staticfile.org/vue/3.3.4/vue.global.prod.min.js"></script>
     <script defer src="https://cdn.staticfile.org/vue-router/4.2.4/vue-router.global.prod.min.js"></script>
     <script defer src="https://cdn.staticfile.org/pinia/2.1.6/pinia.iife.prod.min.js"></script>  
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

vite.config.js 配置

javascript
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers';

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [
        AntDesignVueResolver({
          importStyle: 'less',
          resolveIcons: true,
        }),
      ],
    }),
  ],
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
      },
    },
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build:{
    rollupOptions: {
      external: ['vue', 'vue-router', 'pinia', 'ant-design-vue'],
      output: {
        manualChunks: {
          'utils': ['axios', 'lodash']
        },
        globals: {
          vue: 'Vue',
          'vue-router': 'VueRouter',
          pinia: 'Pinia',
          'ant-design-vue': 'antd'
        }
      }
    },
    chunkSizeWarningLimit: 1500,
  },
})

👆

  1. 此时 Vue全家桶从 CDN 加载,
  2. UI 库和工具库还是从本地打包
  3. 有备用 CDN 源,可以防止 CDN 加载失败
  • 优势: ✅ 利用 CDN 缓存加速 ✅ 减小服务器压力 ✅ 首次加载更快 ✅ 有备用方案,更可靠
  • 风险控制: ✅ 多 CDN 源备份 ✅ 失败自动切换 ✅ 只把最稳定的库放 CDN ✅ 其他依赖还是本地打包

external配置:

  • 优点: ✅ 完全不打包这些库,体积最小 ✅ 可以利用 CDN 缓存 ✅ 减少构建时间
  • 缺点: ❌ 强依赖 CDN 的可用性 ❌ 需要手动管理 CDN 版本 ❌ 可能出现版本不匹配问题

manualChunks 配置

  • 优点: ✅ 更可控,不依赖外部资源 ✅ 版本可控,确保一致性 ✅ 适合私有部署 ✅ 便于调试
  • 缺点: ❌ 打包体积相对较大 ❌ 无法利用公共 CDN 缓存 ❌ 构建时间较长

此时打包后文件大小约为 1161.22kB,压缩后为 351.60kB