vite 优化

1,294 阅读2分钟

分包策略

将第三方包单独打包出去

import { defineConfig } from 'vite';
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // 将 lodash 单独打包
          lodash: ['lodash'],
          // 将 moment 单独打包
          moment: ['moment'],
        },
      },
    },
  },
});

image.png

按页面或功能模块拆分

import { defineConfig } from 'vite';
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return 'vendor';
          }
          if (id.includes('src/pages/')) {
            return 'pages'; // 按页面拆分
          }
          if (id.includes('src/components/')) {
            return 'components'; // 按组件拆分
          }
          if (id.includes('src/utils/')) {
            return 'utils'; // 按工具函数拆分
          }
        },
      },
    },
  },
});

image.png

gzip 压缩

gzip压缩文件

 cnpm i vite-plugin-compression -D
   viteCompression({
      verbose: true, // 是否在控制台中输出压缩结果
      disable: false,
      threshold: 10240, // 如果体积大于阈值,将被压缩,单位为b,体积过小时请不要压缩,以免适得其反
      algorithm: 'gzip', // 压缩算法,可选['gzip',' brotliccompress ','deflate ','deflateRaw']
      ext: '.gz',
      deleteOriginFile: true // 源文件压缩后是否删除(我为了看压缩后的效果,先选择了true)
    })

动态导入

基本用法

  • 动态导入使用的是 JavaScript 中的标准语法 import(),这个语法返回一个 Promise,该 Promise 在模块加载完成后会resolve为模块的导出值。
// 示例:动态导入一个模块
const module = import('./path/to/module.js');

module.then(module => {
  // 使用导入的模块
  console.log(module.default); // 访问模块的默认导出
}).catch(error => {
  // 处理加载模块失败的情况
  console.error('模块加载失败:', error);
});

使用动态导入的场景

  1. 按需加载:根据用户的行为或者当前页面的情况,动态加载所需的模块,以减少初始加载时间。
  2. 懒加载路由:在使用 Vue Router 或者其他路由库时,可以通过动态导入路由组件来实现懒加载,从而优化页面加载性能。
  3. 条件加载:根据条件或者环境来决定加载不同的模块,以增强应用的灵活性和可配置性。

在 Vue 组件中使用动态导入

在 Vue 组件中,动态导入模块可以通过异步组件和 Vue 的 defineAsyncComponent 实现:

<template>
  <div>
    <button @click="loadComponent">加载组件</button>
    <template v-if="Component">
      <Component/>
    </template>
  </div>
</template>

<script>
import { defineAsyncComponent, ref } from 'vue';

export default {
  setup() {
    const Component = ref(null);

    const loadComponent = async () => {
      Component.value = await import('./path/to/MyComponent.vue');
    };

    return {
      loadComponent,
      Component,
    };
  },
};
</script>

CDN

CDN 加速

cnpm i vite-plugin-cdn-import -D
    importToCDN({
      modules: [
        autoComplete('vue'),
        {
          // 引入时的包名
          name: 'element-plus',
          // app.use(), 全局注册时分配给模块的变量
          var: 'ElementPlus',
          // 根据自己的版本号找到对应的CDN网址
          path: 'https://cdn.jsdelivr.net/npm/element-plus',
          // 根据自己的版本号找到对应的CDN网址
          css: 'https://cdn.jsdelivr.net/npm/element-plus/dist/index.css',
        },
      ],
    }),

 rollup

cnpm i rollup-plugin-external-globals -D
  • index.html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite App</title>
  <link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
  <!-- 导入 Vue 3 -->
  <script src="https://cdn.jsdelivr.net/npm/vue@3.4.6/dist/vue.global.min.js"></script>
  <!-- 导入组件库 -->
  <script src="//unpkg.com/element-plus"></script>
</head>

<body>
  <div id="app"></div>
  <script type="module" src="/src/main.ts"></script>
</body>

</html>
import externalGlobals from 'rollup-plugin-external-globals'
export default defineConfig({
build: {
  rollupOptions: {
    external: ['vue', 'element-plus'],
      plugins: [
        externalGlobals({
          vue: 'Vue',
          'element-plus': 'ElementPlus',
        }),
      ],
  }
}
})

使用 CDN 未必会加快速度,只能减小打包体积,因为对应 js 和 css 需要从远程地址读取