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

相关推荐
weixin_382395231 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__1 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.2 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~3 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华3 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子6 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅6 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni6 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学7 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端