打包体积膨胀往往不是因为业务代码写得多,而是引入了整个组件库或工具库,但实际只用到了其中一小部分。按需引入就是解决这个问题的核心手段:只用多少,打包多少。
组件库按需引入:以 Element Plus 为例
像 Element Plus 这样的组件库通常包含几十甚至上百个组件,如果直接全量注册,打包后的体积会非常可观。按需引入有两种主流方式:手动按需导入 和 自动按需导入。
方式一:手动按需导入
直接引入你实际用到的组件,并手动注册:
// main.js
import { createApp } from 'vue'
import { ElButton, ElInput, ElTable } from 'element-plus'
import 'element-plus/theme-chalk/base.css'
import 'element-plus/theme-chalk/button.css'
import 'element-plus/theme-chalk/input.css'
import 'element-plus/theme-chalk/table.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElButton)
app.use(ElInput)
app.use(ElTable)
app.mount('#app')
这种方式精确控制,但每引入一个组件都要手动写注册代码和样式文件,当用到十几个组件时会变得繁琐。更推荐下面这种自动化方案。
方式二:自动按需导入(推荐)
借助 Vite 插件 unplugin-vue-components,它会在编译时自动解析模板中使用的组件,按需引入组件和样式,无需手动注册。配置极简:
npm install -D unplugin-vue-components
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [ElementPlusResolver()]
})
]
})
配置完成后,你就可以直接在模板中使用 Element Plus 组件,无需导入和注册:
<template>
<el-button type="primary">点击</el-button>
<el-input v-model="input" />
</template>
插件会在编译时自动引入 ElButton 和 ElInput 及其样式,打包结果只包含这两个组件,其他上百个组件完全不会进入构建产物。
其他主流组件库的按需方案
- Ant Design Vue:同样可用
unplugin-vue-components搭配AntDesignVueResolver。 - Naive UI:插件支持
NaiveUiResolver,用法类似。 - Vant:
unplugin-vue-components提供VantResolver。
如果你的构建工具是 Webpack,可以使用对应的 Webpack 插件(如 babel-plugin-import)来实现类似的功能,但如今 Vite + unplugin 的组合更简洁高效。
工具库按需加载:以 Lodash 为例
工具库如 Lodash 也是一个体积大头。直接 import _ from 'lodash' 会把整个库打进去(未压缩约 70KB+)。正确的做法是只引入用到的函数:
// 不推荐:引入整个 lodash
import _ from 'lodash'
_.cloneDeep(obj)
// 推荐:按函数引入
import cloneDeep from 'lodash/cloneDeep'
cloneDeep(obj)
现代构建工具(Vite/Webpack)配合 ES Modules 的 Tree Shaking,能够识别到这种按需引入并剔除未使用的代码。但需要注意,有些工具库(旧版 Lodash)没有提供合理的 ES Module 导出结构,此时可以用 lodash-es 这个专门用 ESM 格式打包的版本:
npm install lodash-es
import { cloneDeep, throttle } from 'lodash-es'
这样 Tree Shaking 能完美生效,只打包你实际使用的函数。
实用技巧:如果你不确定某个库是否支持 Tree Shaking,可以查看它的 package.json 中是否有 "module" 字段指向 ESM 版本,或者使用打包分析工具(如 rollup-plugin-visualizer)检查最终产物中该库的实际包含范围。
通用的按需加载原则
- 优先使用 ESM 模块导入,而非
require。 - *避免使用
importas X from 'lib' 这种全量导入**,除非你确定要使用该库的所有导出内容。 - 定期检查构建产物体积,用可视化分析工具发现意外打入的模块(比如忘记移除的实验性引入、某个第三方库的巨型依赖等)。
- 注意间接依赖:有时即使你按需引入了组件库,它内部引入的图标库或样式文件可能是全量的。
unplugin-vue-components这类工具也针对常用图标库做了按需解析(如 Element Plus 图标),但要注意配置或版本兼容。
实际收益
以一个使用了 15 个 Element Plus 组件的管理后台为例,全量引入时依赖体积约 800KB(gzip 前),按需引入后可能降到 200KB 以下——直接砍掉了 4 倍的体积。而这一切只需要在配置文件中加几行代码,开发体验毫无影响。对于首屏加载有很大优化空间的项目,这是性价比最高的手段之一。