CClara轻量论坛系统

用Vite从零搭建Vue3组件库并发布到npm的完整流程。

不能说的秘密
不能说的秘密 星耀SVIP星耀SVIP
发布于 2026-08-16 10:08 ·133 浏览 ·0 回复
内容摘要

介绍如何用 Vite 从零搭建 Vue3 组件库并发布到 npm,核心包括手动初始化工程、用 build.lib 配置组件入口、通过 vite-plugin-dts 生成类型声明、将 vue 设为 external 避免重复打包,按组件目录统一导出并用 withInstall 支持注册,样式采用 SCSS 变量与 CSS 自定义属性并以 BEM 前缀替代 scoped。

当你想做个组件库,而不是又写一遍业务代码

前端干久了,总有一种冲动:把常用的按钮、弹窗、表单封装成自己的组件库,放到 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 帮你扫清了工具链的障碍,剩下的就看你的审美和对场景的理解了。

本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-194.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~