Skip to content

按需引入指南

QXS-BNS 组件库采用现代化的构建策略,通过自动化工具实现按需引入和最小化打包体积。

🎯 设计目标

  • 按需引入 - 只引入实际使用的组件和依赖
  • 最小体积 - 避免不必要的依赖打包
  • 自动化 - 构建时自动处理依赖关系
  • 灵活配置 - 支持不同项目场景的配置需求

🏗️ 依赖架构

核心依赖

依赖类型说明适用场景
Element Plus桌面端 UI 组件库管理后台、数据展示
ECharts图表库数据可视化
TinyMCE富文本编辑器内容编辑
Lodash工具函数库通用工具函数
VueUseVue 工具库Vue 3 增强功能
高德地图地图服务地理位置相关功能

自动化插件

1. 组件自动引入 (internal/plugins/components.js)

javascript
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import rollupComponents from 'unplugin-vue-components/rollup'
import viteComponents from 'unplugin-vue-components/vite'

export default function createComponents() {
  const { TOOL = 'rollup', importStyle = 'sass' } = process.env
  const Components = TOOL === 'vite' ? viteComponents : rollupComponents
  return Components({
    resolvers: [
      ElementPlusResolver({
        importStyle: importStyle === 'false' ? false : importStyle,
      }),
    ],
    include: [/\.vue$/, /\.vue\?vue/, /\.tsx$/],
    dts: './typings/components.d.ts',
  })
}

2. API 自动导入 (internal/plugins/auto-import.js)

javascript
import rollupAutoImport from 'unplugin-auto-import/rollup'
import viteAutoImport from 'unplugin-auto-import/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default function createAutoImport() {
  const { TOOL = 'rollup', importStyle = 'sass' } = process.env
  const autoImport = TOOL === 'vite' ? viteAutoImport : rollupAutoImport

  return [
    autoImport({
      imports: [
        'vue',
        '@vueuse/core',
        ...importsExpand,
      ],
      dts: './typings/auto-imports.d.ts',
      resolvers: [
        ElementPlusResolver({
          importStyle: importStyle === 'false' ? false : importStyle,
        }),
      ],
    }),
  ]
}

📦 当前组件依赖情况

已实现组件

组件名主要依赖说明
QxsDataChartElement Plus, ECharts数据图表组件
QxsFileUploadElement Plus文件上传组件
QxsImageUploadElement Plus图片上传组件
QxsFixedActionBarVueUse固定操作栏
QxsPhotoCropTool无外部依赖图片裁剪工具
QxsTinyMceEditorTinyMCE富文本编辑器
QxsSubjectListElement Plus题目列表组件

外部依赖配置

packages/components/rollup.config.js 中配置了外部依赖:

javascript
external: [
  'vue',
  /^element-plus/,
  '@amap/amap-jsapi-loader',
  'echarts',
  /^tinymce/,
  'lodash-es',
  '@element-plus/icons-vue',
  '@vueuse/core',
  '@qxs-bns/directives',
  '@qxs-bns/utils',
  '@qxs-bns/hooks',
  '@qxs-bns/icons',
  'unocss'
],

💡 使用示例

手动按需引入

typescript
// 手动引入需要的组件
import {
  QxsFixedActionBar,    // 轻量级组件
  QxsPhotoCropTool,     // 无外部依赖
  QxsDataChart,         // 依赖 Element Plus + ECharts
  QxsFileUpload         // 依赖 Element Plus
} from '@qxs-bns/components'

// 样式按需引入
import '@qxs-bns/theme-chalk/src/fixed-action-bar.scss'
import '@qxs-bns/theme-chalk/src/photo-crop-tool.scss'
import '@qxs-bns/theme-chalk/src/data-chart.scss'
import '@qxs-bns/theme-chalk/src/file-upload.scss'

自动按需引入配置

typescript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [
        ElementPlusResolver(),
        // QXS-BNS 组件自动引入
        (componentName) => {
          if (componentName.startsWith('Qxs'))
            return { name: componentName, from: '@qxs-bns/components' }
        }
      ]
    }),
    AutoImport({
      imports: ['vue', '@vueuse/core'],
      resolvers: [ElementPlusResolver()]
    })
  ]
})

项目场景配置

移动端项目

typescript
// 移动端项目 - 优先使用轻量级组件
import {
  QxsFixedActionBar,    // 移动端友好
  QxsPhotoCropTool,     // 图片处理
  // 避免使用重依赖组件
} from '@qxs-bns/components'

桌面端项目

typescript
// 桌面端项目 - 可以使用所有组件
import {
  QxsDataChart,         // 数据可视化
  QxsFileUpload,        // 文件上传
  QxsImageUpload,       // 图片上传
  QxsTinyMceEditor,     // 富文本编辑
  QxsSubjectList,       // 业务组件
} from '@qxs-bns/components'

📝 构建配置详解

Rollup 构建配置

packages/components/rollup.config.js 中,我们配置了外部依赖,确保这些依赖不会被打包到组件库中:

javascript
external: [
  'vue',                        // Vue 3 核心
  /^element-plus/,             // Element Plus 相关
  '@amap/amap-jsapi-loader',   // 高德地图
  'echarts',                   // 图表库
  /^tinymce/,                  // 富文本编辑器
  'lodash-es',                 // 工具函数库
  '@element-plus/icons-vue',   // Element Plus 图标
  '@vueuse/core',              // Vue 工具库
  '@qxs-bns/directives',       // 内部指令库
  '@qxs-bns/utils',            // 内部工具库
  '@qxs-bns/hooks',            // 内部 Hooks 库
  '@qxs-bns/icons',            // 内部图标库
  'unocss'                     // CSS 框架
],

VitePress 文档配置

docs/.vitepress/config.ts 中配置了文档站点的依赖处理:

javascript
const noExternal = [
  '@amap/amap-jsapi-loader',
  'vitepress-demo-plugin',
  'ans-javascript-sdk',
  'node-waves',
  'dompurify',
  'tinymce',
  'lodash-es',
  '@qxs-bns/components',
]

组件依赖分析

轻量级组件(推荐优先使用)

  • QxsPhotoCropTool - 纯 Vue 实现的图片裁剪工具
  • QxsFixedActionBar - 使用 VueUse 的固定操作栏
  • QxsIcon - 基础图标组件

中等依赖组件

  • QxsSubjectAction - 题目操作组件
  • QxsSubjectLayout - 题目布局组件
  • QxsSubjectType - 题目类型组件

重依赖组件

  • QxsDataChart - 依赖 Element Plus + ECharts
  • QxsFileUpload - 依赖 Element Plus
  • QxsImageUpload - 依赖 Element Plus
  • QxsTinyMceEditor - 依赖 TinyMCE
  • QxsSubjectList - 依赖 Element Plus

🚀 开发指南

创建新组件的最佳实践

1. 确定组件类型和依赖策略

bash
# 轻量级组件 (推荐优先考虑)
- 无外部依赖或只依赖 @vueuse/core
- 适用于移动端、H5 应用
- 打包体积小,性能好

# 功能型组件
- 可以依赖 Element Plus
- 适用于管理后台、数据展示
- 功能丰富但需要考虑体积

2. 组件开发流程

bash
# 1. 创建组件目录结构
mkdir packages/components/src/your-component
cd packages/components/src/your-component

# 2. 创建必要文件
touch index.ts src/your-component.vue style/index.scss

# 3. 实现组件逻辑
# 4. 配置导出和样式
# 5. 更新组件库入口文件

3. 依赖管理规范

typescript
// ✅ 推荐的依赖使用方式
import { ref, computed } from 'vue'
import { useVModel } from '@vueuse/core'

// ❌ 避免直接引入整个库
import * as _ from 'lodash-es'  // 应该按需引入
import _ from 'lodash-es'       // 应该按需引入

// ✅ 正确的按需引入
import { debounce, throttle } from 'lodash-es'

组件开发规范

命名规范

javascript
// ✅ 正确的命名
组件名: QxsFixedActionBar    (PascalCase)
文件名: fixed-action-bar     (kebab-case)
目录名: fixed-action-bar     (kebab-case)

// ❌ 错误的命名
组件名: qxsFixedActionBar    (应该是 PascalCase)
文件名: fixedActionBar       (应该是 kebab-case)

依赖选择原则

  1. 优先级排序

    • 无依赖 > 轻量级依赖 > 重量级依赖
    • @vueuse/core > lodash-es > element-plus > echarts
  2. 避免原则

    • 避免不必要的重依赖
    • 避免依赖版本冲突
    • 避免循环依赖

🔧 故障排除

常见问题

1. 自动引入不生效

bash
# 检查插件配置
# 确认 unplugin-vue-components 和 unplugin-auto-import 已正确配置

# 重新生成类型文件
rm -rf typings/auto-imports.d.ts typings/components.d.ts
pnpm dev  # 重新启动开发服务器

2. Element Plus 样式丢失

bash
# 检查样式导入配置
# 确认 ElementPlusResolver 的 importStyle 配置正确

# 手动引入样式
import 'element-plus/dist/index.css'

3. 构建时依赖错误

bash
# 检查 external 配置
# 确认 rollup.config.js 中的 external 配置包含所有外部依赖

# 检查 TypeScript 配置
pnpm lint:tsc

# 重新安装依赖
rm -rf node_modules
pnpm install

4. 组件库体积过大

bash
# 分析打包体积
pnpm build:components

# 检查是否有不必要的依赖被打包
# 确认 external 配置正确
# 使用 Tree-shaking 优化

📊 性能优化

打包体积优化

bash
# 1. 使用按需引入
import { QxsSpecificComponent } from '@qxs-bns/components'

# 2. 避免全量引入
// 避免
import * from '@qxs-bns/components'

# 3. 样式按需引入
import '@qxs-bns/theme-chalk/src/specific-component.scss'

最佳实践

  1. 依赖最小化 - 只引入必要的组件和依赖
  2. 按需加载 - 使用自动引入插件或手动按需引入
  3. 外部依赖 - 确保大型依赖库配置为 external
  4. Tree-shaking - 利用现代打包工具的 Tree-shaking 特性
  5. 性能监控 - 定期检查打包体积和加载性能

🤝 贡献指南

添加新组件时的依赖管理

当添加新组件时,请遵循以下步骤:

  1. 评估依赖需求

    bash
    # 优先考虑轻量级实现
    # 评估是否真的需要重依赖
    # 考虑移动端兼容性
  2. 更新构建配置

    javascript
    // 如果引入新的外部依赖,需要在 rollup.config.js 中添加到 external 数组
    external: [
      // 现有依赖...
      'new-dependency-package'
    ]
  3. 更新自动引入配置

    javascript
    // 如果需要自动引入新的 API,在 auto-import.js 中配置
    imports: [
      'vue',
      '@vueuse/core',
      'new-dependency-package'  // 新增
    ]
  4. 更新文档

    • 在组件文档中说明依赖情况
    • 更新本依赖管理文档
    • 提供使用示例

提交规范

bash
# 添加新组件
git commit -m "feat(components): 添加 QxsNewComponent 组件

- 实现基础功能
- 依赖 @vueuse/core
- 添加相关文档和示例"

# 依赖配置变更
git commit -m "chore(deps): 优化依赖配置

- 移除不必要的依赖
- 更新 external 配置
- 优化打包体积"

📋 总结

QXS-BNS 组件库通过现代化的依赖管理策略,实现了:

  • 自动化按需引入 - 通过 unplugin 插件实现
  • 外部依赖管理 - 通过 external 配置避免重复打包
  • 灵活的配置选项 - 支持不同项目场景
  • 最小化打包体积 - 只引入实际使用的代码

开发者可以根据项目需求灵活选择组件,同时享受自动化工具带来的便利。

Released under the MIT License.