Vue3:企业级组件库搭建(10)

企业级组件库搭建指南:从架构设计到持续交付


文章目录

文章目录

  • 企业级组件库搭建指南:从架构设计到持续交付
    • 文章目录
    • 一、Monorepo架构设计
      • 1.1 工作区配置
      • 1.2 依赖管理策略
    • 二、组件设计规范体系
      • 2.1 原子设计模型
      • 2.2 组件测试规范
    • 三、主题系统实现方案
      • 3.1 CSS变量架构
      • 3.2 运行时主题切换
    • 四、文档自动化方案
      • 4.1 组件元数据提取
      • 4.2 实时预览沙箱
    • 五、CI/CD流水线建设
      • 5.1 自动化流程设计
      • 5.2 质量门禁策略
    • 六、产物发布策略
      • 6.1 多格式打包配置
      • 6.2 按需加载方案
    • 七、企业级组件库演进方向


一、Monorepo架构设计

现代组件库的基石是稳健的工程架构。我们采用PNPM Workspaces搭建Monorepo结构,实现模块化开发与高效管理:

packages/
├─ components/      # 组件源码
├─ theme/           # 主题引擎
├─ docs/            # 文档系统
├─ cli/             # 脚手架工具
└─ playground/      # 开发调试环境

1.1 工作区配置

// pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'internal/*'
  - 'scripts'

1.2 依赖管理策略

# 全局安装公共依赖
pnpm add -wD typescript vite @types/node

# 模块间添加依赖
pnpm add @your-lib/components -r --filter @your-lib/docs

优势对比

方案 安装速度 磁盘空间 依赖一致性
Multirepo
Pnpm Workspace 快30% 节省40%

二、组件设计规范体系

2.1 原子设计模型

// Button组件接口设计
export interface ButtonProps {
  /**
   * 按钮类型
   * @default 'primary'
   */
  type?: 'primary' | 'ghost' | 'text'
  
  /**
   * 禁用状态
   * @default false
   */
  disabled?: boolean
  
  /**
   * 点击事件处理器
   */
  onClick?: (e: MouseEvent) => void
}

// 实现代码
const Button = defineComponent({
  props: {
    type: { type: String, default: 'primary' },
    disabled: Boolean,
    onClick: Function
  },
  setup(props) {
    const theme = useTheme() // 主题注入
    return () => (
      <button 
        class={[
          'btn', 
          `btn-${props.type}`, 
          theme.value === 'dark' && 'btn-dark'
        ]}
        disabled={props.disabled}
        onClick={props.onClick}
      >
        <slot />
      </button>
    )
  }
})

2.2 组件测试规范

// Button.spec.ts
import { mount } from '@vue/test-utils'
import Button from '../src/Button.vue'

describe('Button Component', () => {
  it('触发点击事件', async () => {
    const onClick = vi.fn()
    const wrapper = mount(Button, {
      props: { onClick }
    })
    
    await wrapper.trigger('click')
    expect(onClick).toHaveBeenCalledTimes(1)
  })

  it('禁用状态下不触发事件', async () => {
    const onClick = vi.fn()
    const wrapper = mount(Button, {
      props: { disabled: true, onClick }
    })
    
    await wrapper.trigger('click')
    expect(onClick).toHaveBeenCalledTimes(0)
  })
})

三、主题系统实现方案

3.1 CSS变量架构

// 基础变量定义
:root {
  --primary-color: #1890ff;
  --text-color: rgba(0, 0, 0, 0.85);
  --border-radius: 4px;
}

// 组件级变量
.btn {
  background: var(--primary-color);
  color: var(--text-color);
  border-radius: var(--border-radius);
}

3.2 运行时主题切换

// ThemeProvider组件
const ThemeContext = Symbol('theme')

export const useTheme = () => {
  const theme = inject(ThemeContext, ref('light'))
  return theme
}

export const ThemeProvider = defineComponent({
  props: {
    theme: { type: String, required: true }
  },
  setup(props, { slots }) {
    const root = ref<HTMLElement>()

    watch(() => props.theme, (val) => {
      document.documentElement.setAttribute('data-theme', val)
    }, { immediate: true })

    provide(ThemeContext, toRef(props, 'theme'))

    return () => (
      <div ref={root}>
        {slots.default?.()}
      </div>
    )
  }
})

四、文档自动化方案

4.1 组件元数据提取

// 自动生成API表格
function parseComponent(code: string) {
  const propsRE = /props:\s*({[\s\S]*?})/g
  const matches = code.match(propsRE)
  return parseProps(matches[1])
}

interface PropMeta {
  name: string
  type: string
  default?: string
  description?: string
}

// 输出Markdown表格
function genMarkdownTable(props: PropMeta[]) {
  return `
| 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
${props.map(p => `| ${p.name} | ${p.type} | ${p.default} | ${p.description} |`).join('\n')}
  `
}

4.2 实时预览沙箱

// 使用Vite插件实现
export function docPlugin() {
  return {
    name: 'doc-plugin',
    transform(code, id) {
      if (id.endsWith('.md')) {
        return code.replace(
          /```vue demo\n([\s\S]*?)```/g, 
          (_, code) => genDemoComponent(code)
        )
      }
    }
  }
}

五、CI/CD流水线建设

5.1 自动化流程设计

# .github/workflows/publish.yml
name: Publish
on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: pnpm/action-setup@v2
      - run: pnpm install
      - run: pnpm build
      - run: pnpm test
      - uses: JS-DevTools/npm-publish@v1
        with:
          token: ${{ secrets.NPM_TOKEN }}

5.2 质量门禁策略

检查项 阈值 失败策略
单元测试覆盖率 ≥ 80% 阻断
构建时间 < 5分钟 警告
包体积增长 < 10% 阻断

六、产物发布策略

6.1 多格式打包配置

// components/package.json
{
  "name": "@your-lib/components",
  "main": "dist/cjs/index.js",
  "module": "dist/esm/index.mjs",
  "types": "dist/types/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/esm/index.mjs",
      "require": "./dist/cjs/index.js"
    }
  }
}

6.2 按需加载方案

// babel-plugin-import
module.exports = function (babel) {
  return {
    visitor: {
      ImportDeclaration(path) {
        const source = path.node.source.value
        if (source === '@your-lib/components') {
          path.node.specifiers.forEach(spec => {
            if (spec.type === 'ImportSpecifier') {
              const component = spec.imported.name
              // 转换为按需引入
              path.insertAfter(
                babel.template.ast`
                  import '${source}/es/${component.toLowerCase()}'
                `
              )
            }
          })
        }
      }
    }
  }
}

七、企业级组件库演进方向

  1. 智能化组件:集成AI辅助设计系统
  2. 跨框架适配:支持React/Solid等框架
  3. 3D可视化:集成Three.js扩展能力
  4. 无障碍支持:通过WAI-ARIA认证

下篇预告:《自动化测试策略(Vitest+Cypress)》将深入:

  • 组件单元测试最佳实践
  • E2E测试的防脆性设计
  • 视觉回归测试方案

你可能感兴趣的:(Vue3,vue.js)