Published on

Vite 打包优化策略

Authors
  • Name
    Twitter

1. 代码分割

代码分割是最有效的优化策略之一,它允许我们将代码拆分成更小的块,按需加载。

路由级别的代码分割

对于 Vue Router:

// router.js
const routes = [
  {
    path: '/',
    component: () => import('./views/Home.vue')
  },
  {
    path: '/about',
    component: () => import('./views/About.vue')
  },
  // 其他路由...
]

export default createRouter({
  // ...
  routes
})

对于 React Router:

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home}/>
          <Route path="/about" component={About}/>
        </Switch>
      </Suspense>
    </Router>
  );
}

2. 依赖优化

优化依赖预构建

// vite.config.js
export default {
  optimizeDeps: {
    include: ['lodash-es', 'vue'], // 强制预构建这些依赖
    exclude: ['your-local-package'], // 排除某些依赖
  }
}

检查未使用的依赖

使用 depcheck 工具来检查未使用的依赖:

npx depcheck

然后根据输出结果移除未使用的依赖。

3. 压缩和最小化

// vite.config.js
import { defineConfig } from 'vite'
import viteCompression from 'vite-plugin-compression'

export default defineConfig({
  build: {
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    }
  },
  plugins: [
    viteCompression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: 'gzip',
      ext: '.gz',
    })
  ]
})

4. 资源优化

图片优化

// vite.config.js
import viteImagemin from 'vite-plugin-imagemin'

export default {
  plugins: [
    viteImagemin({
      gifsicle: {
        optimizationLevel: 7,
        interlaced: false,
      },
      optipng: {
        optimizationLevel: 7,
      },
      mozjpeg: {
        quality: 20,
      },
      pngquant: {
        quality: [0.8, 0.9],
        speed: 4,
      },
      svgo: {
        plugins: [
          {
            name: 'removeViewBox',
          },
          {
            name: 'removeEmptyAttrs',
            active: false,
          },
        ],
      },
    }),
  ],
}

懒加载图片

对于 Vue:

<template>
  <img v-lazy="'/path/to/image.jpg'" />
</template>

<script>
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)
</script>

对于 React:

import { LazyLoadImage } from 'react-lazy-load-image-component';

function MyImage() {
  return (
    <LazyLoadImage
      src="/path/to/image.jpg"
      effect="blur"
    />
  );
}

5. 自定义 Chunk 分割

// vite.config.js
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          'lodash': ['lodash'],
          'vue': ['vue', 'vue-router', 'vuex'],
          'react': ['react', 'react-dom', 'react-router-dom'],
        }
      }
    }
  }
}

6. 按需导入

对于 Ant Design Vue:

// vite.config.js
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    Components({
      resolvers: [AntDesignVueResolver()],
    }),
  ],
})

7. 性能分析

// vite.config.js
import { defineConfig } from 'vite'
import { visualizer } from "rollup-plugin-visualizer";

export default defineConfig({
  plugins: [
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true,
    })
  ]
})