用Vite从零搭建Vue3组件库并发布到npm的完整流程。
当你想做个组件库,而不是又写一遍业务代码
前端干久了,总有一种冲动:把常用的按钮、弹窗、表单封装成自己的组件库,放到 npm 上,下次开新项目直接 `npm install` 一把梭。但真到动手时,很多人卡在「怎么搭工程」「怎么出类型」「怎么发布」这三座大山前。Vite 的出现让这件事变得简单得不像话——今天就带你从零到一,走一遍完整流程。
初始化工程,选对构建配置
别用 `vite create` 那种标准模板,因为我们是组件库,不是应用。手动建个目录,`npm init -y` 后装依赖:
npm install vue@3
npm install -D vite @vitejs/plugin-vue vite-plugin-dts
重点是 Vite 的构建配置。组件的入口不能是 `index.html`,而是我们的组件源码。在 `vite.config.ts` 里用 `build.lib` 模式:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import dts from 'vite-plugin-dts'
export default defineConfig({
plugins: [vue(), dts({ include: ['src'], outDir: 'dist/types' })],
build: {
lib: {
entry: 'src/index.ts',
name: 'MyUI',
formats: ['es', 'umd'],
fileName: (format) => `my-ui.${format}.js`
},
rollupOptions: {
external: ['vue'],
output: {
globals: { vue: 'Vue' }
}
}
}
})
把 `vue` 设为 external 至关重要,否则会把整个 Vue 打包进组件库,导致使用方重复加载。`vite-plugin-dts` 负责自动生成 `.d.ts` 类型声明,这才是 Vue3 组件库的硬通货。
组件写得好,但别把样式锁死
组件库的核心不是把代码塞进 `src/components` 就完事。推荐目录结构:
src/
index.ts // 统一导出
button/
Button.vue
index.ts
modal/
Modal.vue
index.ts
每个组件的 `index.ts` 里加上 `withInstall` 方法——这是组件库的惯例,让用户既可以用 `<MyButton>`,也可以 `app.use(MyButton)` 全局注册:
import type { App } from 'vue'
import Button from './Button.vue'
Button.install = (app: App) => {
app.component(Button.name, Button)
}
export default Button as typeof Button & { install: (app: App) => void }
样式方面,建议用 SCSS 变量 + CSS 自定义属性(CSS Variables)双轨制。CSS 变量可以避免用户覆写样式时被深层的 scoped 选择器卡住。不要用 scoped,而是用统一的 BEM 类名前缀,比如 `my-button`、`my-button--primary`。
发布前最后的魔鬼细节
打包完成后,`dist` 目录会生成 ESM 和 UMD 文件,但真正的考验在 `package.json`:
{
"name": "@yourname/my-ui",
"version": "0.1.0",
"main": "dist/my-ui.umd.js",
"module": "dist/my-ui.es.js",
"types": "dist/types/index.d.ts",
"exports": {
".": {
"import": "./dist/my-ui.es.js",
"require": "./dist/my-ui.umd.js",
"types": "./dist/types/index.d.ts"
},
"./style.css": "./dist/my-ui.css"
},
"files": ["dist"],
"peerDependencies": {
"vue": "^3.2.0"
}
}
注意 `peerDependencies` 声明 Vue 为同行依赖,`files` 只打包 `dist`,别把源码和 node_modules 一起推上去。`exports` 字段是 Node12+ 和现代打包器解析的入口,写不好会让人无法 import 样式。
样式文件怎么出?Vite 默认会把所有被引用的 CSS 抽成一个 `style.css`。但组件库更讲究「按需加载」,建议在组件内部直接 `import './Button.css'`,再用 `build.cssCodeSplit` 开启代码分割。不过对新手而言,一个全量 CSS 先跑通流程更重要。
验证打包,然后发布
发布前必须做本地验证。在 `dist` 目录同级开个测试项目,用 `npm link` 把组件库链过去,写个 `App.vue` 测试按需注册、全局注册、样式引入。这一步能避免发到 npm 上才发现组件根本渲染不出来——别问我怎么知道的。
一切就绪后,执行:
npm login
npm publish --access public
如果你用的是私有 npm 包名,比如 `@mycompany/ui`,不需要 `--access public`,但公共包必须加。
维护比构建更值得关注
流程跑通了,你会发现自己陷入另一个循环:每次改组件代码都要重新打包、更新版本号、再发布。建议用 `changesets` 管理版本更新,或者在 commit 信息里带 `fix:`, `feat:` 前缀配合 semantic-release 自动发版。组件库不是一次性的任务,而是需要长期维护的工程。
最后提醒一句:component library is easy, component design is hard。别本末倒置,先在业务里沉淀几个反复使用组件,把它们抽出来打磨成真正解决痛点的工具,然后才用上面这套流程交给全世界。Vite 帮你扫清了工具链的障碍,剩下的就看你的审美和对场景的理解了。
转载请注明出处,版权归原作者所有。
管理员
黑卡会员