从 0 到 1 搭建 Vue3 + Vite 组件库:流程、规范与最佳实践

引言

在前端开发领域,组件库是提升项目开发效率、保障 UI 一致性的关键工具。随着 Vue3 和 Vite 生态的成熟,搭建一套属于自己或团队的组件库正成为越来越多开发者的需求。本文将详细拆解从初始化项目到发布维护的完整流程,结合工程化规范与最佳实践,带你打造高质量 Vue3 组件库。

一、技术选型与初始化

(一)核心技术栈选择

  • Vue3 :采用 Composition API 实现逻辑复用,借助 <script setup> 语法糖简化组件编写,利用响应式语法糖(如 $ref)提升开发体验。
  • Vite :基于 ESBuild 的极速冷启动、按需编译特性,搭配 vitepress 实现文档站点快速构建,支持 @vitejs/plugin-vue 实现单文件组件编译。
  • TypeScript :为组件提供类型定义,结合 vue-tsc 进行类型检查,保障代码健壮性。
  • CSS 方案 :可选 UnoCSS(原子化 CSS,按需生成样式)、Tailwind CSS(实用优先)或 Scoped Styles + CSS 变量(传统可控方案)。

(二)项目初始化流程

  1. 创建基础工程
bash 复制代码
# 使用 Vite 模板初始化 Vue3 + TS 项目
pnpm create vite@latest my-component-lib -- --template vue-ts
cd my-component-lib
pnpm install
  1. 配置 package.json 基础字段
json 复制代码
{
  "name": "my-component-lib",
  "version": "0.0.1",
  "private": false, // 开源组件库需设为 false
  "main": "dist/lib/index.cjs",
  "module": "dist/lib/index.mjs",
  "types": "dist/lib/index.d.ts",
  "files": ["dist"],
  "scripts": {
    "dev": "vite",
    "build:lib": "vue-tsc && vite build --mode library",
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs"
  }
}
  1. Vite 库模式配置(vite.config.ts
TypeScript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

export default defineConfig({
  plugins: [vue()],
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'MyComponentLib',
      fileName: (format) => `index.${format}.js`
    },
    rollupOptions: {
      external: ['vue'],
      output: {
        globals: { vue: 'Vue' }
      }
    }
  }
})

二、组件开发规范与实践

(一)组件目录结构设计

bash 复制代码
src/
├── components/       # 组件源码
│   ├── Button/       # 按钮组件
│   │   ├── Button.vue
│   │   ├── button.types.ts
│   │   └── index.ts  # 导出组件
│   └── index.ts      # 组件库入口
├── styles/            # 全局样式
│   ├── variables.css # CSS 变量
│   └── index.css     # 样式入口
└── index.ts           # 库导出入口

(二)组件编写规范

  1. Vue3 组件模板(Button.vue
html 复制代码
<template>
  <button 
    class="my-btn" 
    :class="{ 'my-btn--disabled': disabled }" 
    :disabled="disabled" 
    @click="handleClick"
  >
    <slot />
  </button>
</template>

<script setup lang="ts">
import { defineProps, emit } from 'vue'

// Props 定义(支持类型推导)
const props = defineProps({
  disabled: Boolean,
  type: {
    type: String,
    default: 'default',
    validator: (val: string) => 
      ['default', 'primary', 'danger'].includes(val)
  }
})

// 事件定义
const emit = defineEmits(['click'])

const handleClick = () => {
  if (!props.disabled) {
    emit('click')
  }
}
</script>

<style scoped>
.my-btn {
  padding: 8px 16px;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  cursor: pointer;
}
.my-btn--disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
</style>
  1. 类型与接口抽离(button.types.ts
typescript 复制代码
import { PropType } from 'vue'

export type ButtonType = 'default' | 'primary' | 'danger'

export const buttonProps = {
  disabled: Boolean,
  type: {
    type: String as PropType<ButtonType>,
    default: 'default'
  }
} as const

(三)文档与示例编写(Vitepress)

  1. 文档目录结构
bash 复制代码
docs/
├── index.md          # 首页
├── guide/            # 指南文档
│   └── getting-started.md
└── components/       # 组件文档
    └── button.md
  1. 组件文档示例(button.md
markdown 复制代码
# Button 按钮

## 基本用法
<demo src="/src/components/Button/demo/Basic.vue"></demo>

::: details 查看代码
```vue
<template>
  <MyButton type="primary">主要按钮</MyButton>
  <MyButton disabled>禁用按钮</MyButton>
</template>

<script setup lang="ts">
import { MyButton } from 'my-component-lib'
</script>

:::

API 说明

参数 类型 默认值 说明
type ButtonType default 按钮类型
disabled boolean false 是否禁用
bash 复制代码
## 三、工程化与质量保障
### (一)代码规范与校验
1. **ESLint + Prettier 配置**  
```bash
pnpm install eslint eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin prettier eslint-config-prettier -D

.eslintrc.cjs 关键配置:

js 复制代码
module.exports = {
  extends: [
    'plugin:vue/vue3-recommended',
    'eslint:recommended',
    '@typescript-eslint/recommended',
    'prettier'
  ],
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2022
  }
}
  1. 提交规范(Commitlint + Husky)
bash 复制代码
pnpm install @commitlint/cli @commitlint/config-conventional husky -D

commitlint.config.cjs

js 复制代码
module.exports = { extends: ['@commitlint/config-conventional'] }

package.json 添加脚本:

json 复制代码
{
  "scripts": {
    "prepare": "husky install",
    "lint:commit": "commitlint --edit"
  }
}

初始化 Husky:

bash 复制代码
pnpm run prepare
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

(二)单元测试与覆盖率

  1. Vitest 配置
bash 复制代码
pnpm install vitest @vue/test-utils -D

vite.config.ts 添加测试配置:

ts 复制代码
export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    transformMode: {
      web: [/.[jt]sx$/]
    }
  }
})
  1. 组件测试示例(Button.test.ts
ts 复制代码
import { mount } from '@vue/test-utils'
import MyButton from '../Button.vue'

describe('MyButton', () => {
  it('渲染默认按钮', () => {
    const wrapper = mount(MyButton, { slots: { default: '按钮文本' } })
    expect(wrapper.text()).toContain('按钮文本')
    expect(wrapper.classes()).toContain('my-btn')
  })

  it('禁用状态', () => {
    const wrapper = mount(MyButton, { props: { disabled: true } })
    expect(wrapper.attributes('disabled')).toBe('')
    expect(wrapper.classes()).toContain('my-btn--disabled')
  })
})

四、构建与发布

(一)库模式构建

bash 复制代码
pnpm run build:lib

构建后生成 dist/lib 目录,包含:

  • index.cjs:CommonJS 格式
  • index.mjs:ESModule 格式
  • index.d.ts:类型定义文件

(二)文档站点部署

  1. Vitepress 构建
bash 复制代码
pnpm run docs:build

生成 docs/.vitepress/dist 静态站点,可部署至 GitHub Pages、Netlify 或 Vercel。

  1. GitHub Pages 部署示例(deploy-docs.yml
yaml 复制代码
name: Deploy Docs
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v2
        with: version: 8
      - uses: actions/setup-node@v4
        with: node-version: 20
      - run: pnpm install
      - run: pnpm run docs:build
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs/.vitepress/dist

(三)NPM 发布流程

  1. 登录 NPM
bash 复制代码
pnpm login
  1. 发布包
bash 复制代码
pnpm publish --access public

注意:首次发布需确保 package.jsonname 未被占用,可到 NPM 官网 搜索校验。

五、维护与生态扩展

(一)版本管理与 CHANGELOG

使用 standard-version 自动生成 CHANGELOG:

bash 复制代码
pnpm install standard-version -D

添加脚本到 package.json

json 复制代码
{
  "scripts": {
    "release": "standard-version"
  }
}

执行 pnpm run release 自动生成版本号、CHANGELOG 并提交。

(二)生态集成

  • Nuxt3 适配 :创建 Nuxt 模块,通过 defineNuxtModule 注册组件库。
  • Unocss 预设:封装组件库专属原子化样式预设,方便快速接入。
  • Playground 搭建 :使用 vitepressstackblitz 提供在线示例,增强用户体验。

结语

搭建 Vue3 + Vite 组件库是一个涵盖工程化、规范化、生态化的系统性工程。从组件开发的细粒度把控,到构建发布的自动化流程,再到长期维护的版本管理,每一步都决定了组件库的质量与生命力。通过本文的实践,你不仅能打造一套属于自己的组件库,更能深入理解前端工程化的核心逻辑。不妨从一个基础组件开始,逐步迭代,让你的组件库成为团队效率的助推器,甚至开源社区的优质资产。

相关推荐
猫头_25 分钟前
uni-app 转微信小程序 · 避坑与实战全记录
前端·微信小程序·uni-app
天生我材必有用_吴用28 分钟前
网页接入弹窗客服功能的完整实现(Vue3 + WebSocket预备方案)
前端
海拥33 分钟前
8 Ball Pool:在浏览器里打一局酣畅淋漓的桌球!
前端
Cache技术分享40 分钟前
148. Java Lambda 表达式 - 捕获局部变量
前端·后端
YGY Webgis糕手之路1 小时前
Cesium 快速入门(二)底图更换
前端·经验分享·笔记·vue
神仙别闹1 小时前
基于JSP+MySQL 实现(Web)毕业设计题目收集系统
java·前端·mysql
前端李二牛1 小时前
Web字体使用最佳实践
前端·http
YGY_Webgis糕手之路1 小时前
Cesium 快速入门(六)实体类型介绍
前端·gis·cesium
Jacob02341 小时前
UI 代码不写也行?我用 MCP Server 和 ShadCN 自动生成前端界面
前端·llm·ai编程
爱泡脚的鸡腿1 小时前
Vue第五次笔记
前端·vue.js