使用 unplugin-vue-components 后 Vite 启动很慢
Vite 以启动快著称,我的项目也使用了 Vite ,但启动速度却不是想象中的那么快。项目使用的是 ElementPlus 组件库,根据官方文档的推荐使用了 unplugin-vue-components 做按需引入,随着项目越做越大,启动速度也是越来越慢。
问题原因
由于实在是太慢了,所以做了一次排查,最后发现是使用了 unplugin-vue-components 导致慢,将 ElementPlus 改成全量加载启动速度是非常的快。翻了一下 unplugin-vue-components 的 GitHub Issues ,原来也有其他人遇到同样的问题。作者说是 Vite 的问题 #301
解决思路
目前 Vite 和 unplugin-vue-components 都没有解决这个问题,所以自己先暂时想个办法解决。
解决思路是这样的,因为全量加载很快,所以打算只在生产打包时使用 unplugin-vue-components ,开发模式则不使用。但由于使用 unplugin-vue-components 是不需要在项目代码中直接引入 ElementPlus ,所以只需要做到下面两种情况即可:
- dev 模式需要 引入 ElementPlus
- build 模式 不引入 ElementPlus
按照上面的意思,生产打包时不引入 ElementPlus ,开发模式启动时引入 ElementPlus 。所以我的解决方案是:通过 Vite(Rollup) 插件的 transform
钩子给 src/main.ts
注入 ElementPlus ,这样就不需要对业务代码做任何的处理。
编写 Vite 插件
build/plugins/fullImportPlugin.ts:
import * as path from 'path'
import type { Plugin, ResolvedConfig } from 'vite'
export default function fullImportPlugin () {
let config: ResolvedConfig
return <Plugin>{
name: 'fullImportElementPlus',
async configResolved (conf) {
config = conf
},
transform (code, id) {
// 判断当前处理的是否是 _src/main.ts_
if (path.join(config.root, 'src/main.ts') === id) {
const name = 'ElementPlus'
// 引入 ElementPlus 和 样式
const prepend = `import ${name} from 'element-plus';\nimport 'element-plus/dist/index.css';\n`
// 通过匹配字符串来使用 ElementPlus (此处替换规则根据 main.ts 的情况而定)
// 相当于将字符串 `app.use(router).mount('#app')` 替换成 `app.use(router).use(ElementPlus).mount('#app')`
code = code.replace('.mount(', ($1) => `.use(${name})` + $1)
return prepend + code
}
return code
}
}
}
使用编写的插件
vite.config.ts:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import fullImportPlugin from './build/plugins/fullImportPlugin'
export default defineConfig(({ mode }) => {
return {
plugins: [
vue(),
mode === 'development'
? fullImportPlugin()
: Components({
resolvers: [ElementPlusResolver()]
})
],
}
})
至此已经解决了启动慢的问题了。