上一节靠「消费方全局 app.use(ElementPlus)」打通了链路,这一节把第二条路线真正跑通:让组件库内部按需解析并带出自己用到的 Element Plus 组件和样式,从而 Playground 不必再全局安装 Element Plus。本文把「局部使用 Element Plus」拆成作者开发体验和消费方运行体验两层,讲清 unplugin-auto-import + unplugin-vue-components + ElementPlusResolver 的组合、库产物样式如何通过 exports["./style.css"] 暴露、element-plus 到底该进 peerDependencies 还是 devDependencies,以及这条路线在体积与升级上的代价。
unplugin-auto-import + unplugin-vue-components + ElementPlusResolver 降低手写导入成本exports["./style.css"] 暴露,而非自定义非标准字段element-plus 进入 peerDependencies 还是 devDependencies课程里很容易把两件事混成一件:作者开发组件时希望自动按需引入 Element Plus 组件和 Vue API;消费方使用组件库时希望不必全局安装 Element Plus。这两层关联但不是同一问题:
ElAvatar 要不要手写 import、computed 要不要手写 import,解决方案是自动导入插件;element-plus、还要不要在 main.ts 里 app.use(ElementPlus),解决方案是依赖是否 external、样式是否随库分发。自动导入插件解决的是作者写代码的体验,不直接决定最终库产物的依赖边界。
Element Plus 官方 Quick Start 当前给出的按需导入方案,就是 unplugin-auto-import + unplugin-vue-components + ElementPlusResolver。在组件库项目里,这套方案同时解决两类问题:自动导入 Vue API(如 computed、ref),以及自动解析模板中的 Element Plus 组件(如 ElAvatar)。
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: ['vue', '@vueuse/core'],
resolvers: [ElementPlusResolver()],
dts: true,
}),
Components({
resolvers: [ElementPlusResolver()],
dts: true,
}),
],
})AutoImport 负责自动导入脚本里用到的 API,Components 负责自动注册模板里用到的组件,ElementPlusResolver 把 Element Plus 纳入自动按需解析体系,dts: true 生成类型声明降低编辑器异常。@vueuse/core 如果组件内部要用才装,否则自动导入里不必提前塞太多东西。
如果组件库内部引用了 ElAvatar,构建器和解析器会把组件相关样式一起带到库的 CSS 中。从消费方角度看,意味着不一定非要在入口再手动引 element-plus/dist/index.css,但必须把组件库样式入口引进来(import 'el-admin-components/style.css')。
Vite 官方库模式文档给出的推荐方式是:如果库会额外产出 CSS 文件,就在 package.json.exports 中显式暴露 ./style.css,而不是自定义一个不规范的 exports.style 字段。
{
"name": "el-admin-components",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/el-admin-components.js",
"require": "./dist/el-admin-components.umd.cjs"
},
"./style.css": "./dist/el-admin-components.css"
}
}样式文件名默认跟 build.lib.fileName 相关,也可通过 cssFileName 单独控制。一旦想让消费方稳定引用样式,最好明确给出 ./style.css 这样的子路径出口。
element-plus 的归属取决于是否 external如果 external 掉 element-plus,消费方运行时必须提供它,那它应当进入 peerDependencies(同时为本地开发把它放进 devDependencies);如果把 element-plus 打进产物,消费方不一定需要直接安装它,但你要接受包体积增加和依赖耦合增强。本地实验阶段把 element-plus 先装到开发依赖可以成立,但准备发布前归属必须和 external 策略一致,否则消费方最容易遇到「本地能跑、发出去别人不能用」。
{
"peerDependencies": {
"vue": "^3.0.0",
"element-plus": "^2.0.0",
"@vueuse/core": "^10.0.0"
},
"devDependencies": {
"element-plus": "^2.0.0"
}
}课程在 Playground 里去掉 app.use(ElementPlus) 后组件仍能渲染,说明组件库自己吸收了需要的局部 Element Plus 能力。但副作用很明确:dist 体积增大、组件库和 Element Plus 样式更紧耦合、后续走 CDN / external 策略更麻烦、新组件或新样式能力很难像「全局安装 Element Plus」那样自然继承。
自动导入 Vue API 和自动解析 Element Plus 组件,不等于可以放弃显式依赖管理——构建链路会帮你少写 import,但不会替你决定架构边界。对 Vue API 这类语法层能力,自动导入对打包边界影响很小;对 Element Plus 这类大体量 UI 依赖,是否开启自动解析会直接影响产物体积、样式分发、external 策略和使用者负担。
这节课真正的结论不是「哪种方案绝对更好」,而是:在组件库从 0 到 1 阶段,先把两条链路都验证一遍,后面才能有依据做取舍。课程最后更推荐 external 掉 Element Plus,这个判断有工程经验支撑——尤其当组件库主要服务同一套 admin 体系内部项目时,external 策略通常更划算。
| 问题 | 原因 | 解决方案 |
|---|---|---|
去掉 Playground 的 app.use(ElementPlus) 后组件能渲染但样式丢了 | 组件库 JS 已带能力,但样式入口没引入 | 给组件库导出 ./style.css 并在消费方显式导入 |
ElementPlusResolver 配了但构建报找不到 element-plus | 构建期依赖里根本没装 | 在组件库项目至少安装 element-plus 作为开发依赖 |
组件库发布后别人还得装 element-plus 但文档没写 | 实际走 external 方案,依赖边界没说清 | 写入 peerDependencies 并在 README 标明 |
| 组件库包体积明显变大 | 把 Element Plus 局部能力和样式打进产物 | 评估是否改为 external 策略 |
课程说 exports.style 但消费方导入不稳定 | 样式出口设计不规范 | 改成 exports["./style.css"] |
| 想保留 Vue API 自动导入但不想把 Element Plus 打进库 | 把自动导入工具和依赖打包策略混在一起 | 保留 AutoImport 对 Vue API 的支持,收敛 ElementPlusResolver 相关打包策略 |