vite性能优化-分包策略

avatar
前端

优化目标

  1. 解决js包之间的依赖问题,提升加载时间
  2. 细小js文件合并,减少js数量
  3. 剔除无关js,减小体积

实现方式

1. 解决js包之间的依赖问题,提升加载时间

问题描述

image.png 分析network加载顺序可知, 页面js依赖preview.js,previw.js执行时间过长,还需要等待main.js执行完之后再加载。考虑把previw.js跟main.js合并,将preview.js加载时间提前,能提升整体js加载时长。

vite配置修改

你可以通过配置 build.rollupOptions.output.manualChunks 来自定义 chunk 分割策略(查看 Rollup 相应文档)。在 Vite 2.8 及更早版本中,默认的策略是将 chunk 分割为 index 和 vendor。这对一些 SPA 来说是好的策略,但是要对所有应用场景提供一种通用解决方案是非常困难的。从 Vite 2.9 起,manualChunks 默认情况下不再被更改。你可以通过在配置文件中添加 splitVendorChunkPlugin 来继续使用 “分割 Vendor Chunk” 策略:

js

// vite.config.js
import { splitVendorChunkPlugin } from 'vite'
export default defineConfig({
  plugins: [splitVendorChunkPlugin()],
})

也可以用一个工厂函数 splitVendorChunk({ cache: SplitVendorChunkCache }) 来提供该策略,在需要与自定义逻辑组合的情况下,cache.reset() 需要在 buildStart 阶段被调用,以便构建的 watch 模式在这种情况下正常工作。

WARNING

你应该使用 build.rollupOptions.output.manualChunks 函数形式来使用此插件,如下面例子所示,另外还需要将默认的插件去掉,不然会走默认方式。另外如果使用对象形式,插件将不会生效。

    build: {
      rollupOptions: {
        manualChunks(id) {
          if (id.includes('preview/main') || id.includes('views/preview')) {
            return 'mianPreview';
          }
        },
      },
    },

运行结果

image.png js合并成功 previw.js与main.js合并成功,previw加载提前,页面加载更快。

2. 细小js文件合并,减少js数量

问题描述

将同文件夹下的琐碎js文件,合并至同一个文件。

vite配置

合并含有composables的文件到一个js。

    build: {
      rollupOptions: {
        manualChunks(id) {
          if (id.includes('packages/composables')) {
            return 'composables';
          }
        },
      },
    },

运行结果

image.png packages/composables文件夹下的文件都被打包到composables.js里面

3. 剔除无关js,减小体积

问题描述

image.png

image.png 标注出的js是项目中使用不到的文件,实际上只需要render函数,但是实际上会把文件中引入的都打包进去

vite配置

如果你的vite版本是3.0可以使用具名导入

具名导入

也可能你只想要导入模块中的部分内容,那么可以利用 import 选项。

const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
// vite 生成的代码
const modules = {
  './dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),
  './dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),
}

当与 eager 一同存在时,甚至可以对这些模块进行 tree-shaking。

const modules = import.meta.glob('./dir/*.js', {
  import: 'setup',
  eager: true,
})
// vite 生成的代码
import { setup as __glob__0_0 } from './dir/foo.js'
import { setup as __glob__0_1 } from './dir/bar.js'
const modules = {
  './dir/foo.js': __glob__0_0,
  './dir/bar.js': __glob__0_1,
}

设置 import 为 default 可以加载默认导出。

const modules = import.meta.glob('./dir/*.js', {
  import: 'default',
  eager: true,
})
// vite 生成的代码
import __glob__0_0 from './dir/foo.js'
import __glob__0_1 from './dir/bar.js'
const modules = {
  './dir/foo.js': __glob__0_0,
  './dir/bar.js': __glob__0_1,
}

如果是2.0版本,则不支持具名导入,需要手动拆分文件,将render函数拆成单独的文件,仅导入该文件。

运行结果

打包文件不存在框中的js。

结论

vite的功能还是比较强大的,可以参考官方文档cn.vitejs.dev/ 以及rollupjs.org/ 配置