@bm-fe/icons
v0.1.0-beta.0
Published
BitMart 图标库(SVG 源 + React 适配层)
Readme
@bm-fe/icons
BitMart 图标库,提供 SVG 源文件和框架适配层。
特性
- 🎨 SVG 单一事实源:所有图标源文件统一管理
- ⚛️ React 组件:开箱即用的 React 适配层
- 🟢 Vue 支持:通过 unplugin-icons / vite-svg-loader 引入
- 🚀 自动生成:组件通过生成器自动生成,禁止手改
- 📦 类型安全:完整的 TypeScript 类型定义
- 🎯 语义稳定:图标 API 长期稳定,设计变更不影响业务代码
- 🖼️ PNG 优化:国旗图标自动压缩,节省 67%+ 空间
安装
pnpm add @bm-fe/iconsReact 使用
直接导入生成的 React 组件:
import { Add, Close, ArrowUp } from '@bm-fe/icons';
// 或者
import { Add, Close, ArrowUp } from '@bm-fe/icons/react';
function App() {
return (
<div>
<Add size={16} />
<Close size={20} />
<ArrowUp size="1.25em" />
</div>
);
}React 组件 Props
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| size | number \| string | 24 | 图标尺寸 |
| className | string | - | 自定义类名 |
| style | CSSProperties | - | 自定义样式 |
Vue 使用
方式一:unplugin-icons(推荐)
unplugin-icons 支持 Vue 2、Vue 3、Vite、Webpack 等多种构建工具。
1. 安装依赖
pnpm add -D unplugin-icons unplugin-vue-components2. 配置 Vite(Vue 3)
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import Icons from 'unplugin-icons/vite';
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
export default defineConfig({
plugins: [
vue(),
Icons({
compiler: 'vue3',
customCollections: {
// 自定义 bm 图标集合,指向 @bm-fe/icons 的 SVG 目录
bm: FileSystemIconLoader(
'./node_modules/@bm-fe/icons/svg/primary',
(svg) => svg.replace(/^<svg /, '<svg fill="currentColor" ')
),
'bm-product': FileSystemIconLoader(
'./node_modules/@bm-fe/icons/svg/product'
),
'bm-coin': FileSystemIconLoader(
'./node_modules/@bm-fe/icons/svg/coin'
),
},
}),
],
});3. 配置 Vue 2 / Nuxt 2(Webpack)
// nuxt.config.js 或 vue.config.js
const Icons = require('unplugin-icons/webpack');
const { FileSystemIconLoader } = require('unplugin-icons/loaders');
module.exports = {
configureWebpack: {
plugins: [
Icons({
compiler: 'vue2',
customCollections: {
bm: FileSystemIconLoader(
'./node_modules/@bm-fe/icons/svg/primary',
(svg) => svg.replace(/^<svg /, '<svg fill="currentColor" ')
),
},
}),
],
},
};4. 在组件中使用
<template>
<div>
<!-- 自动导入方式 -->
<IBmAdd class="w-6 h-6 text-blue-500" />
<IBmClose class="w-4 h-4" />
<!-- 显式导入方式 -->
<AddIcon class="w-6 h-6" />
</div>
</template>
<script setup>
// 显式导入(可选)
import AddIcon from '~icons/bm/add';
</script>命名规则: I + 集合名(首字母大写) + 图标名(PascalCase)
svg/primary/add.svg→<IBmAdd />svg/product/google.svg→<IBmProductGoogle />
方式二:vite-svg-loader
仅支持 Vite 项目,更轻量但功能较少。
1. 安装
pnpm add -D vite-svg-loader2. 配置 Vite
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import svgLoader from 'vite-svg-loader';
export default defineConfig({
plugins: [vue(), svgLoader()],
resolve: {
alias: {
'@icons': './node_modules/@bm-fe/icons/svg',
},
},
});3. 使用
<template>
<AddIcon class="w-6 h-6 text-current" />
</template>
<script setup>
import AddIcon from '@icons/primary/add.svg?component';
</script>路径别名配置
推荐在项目中配置 @icons 别名:
Vite:
// vite.config.ts
export default defineConfig({
resolve: {
alias: {
'@icons': './node_modules/@bm-fe/icons/svg',
},
},
});Webpack / Vue CLI:
// vue.config.js
const path = require('path');
module.exports = {
configureWebpack: {
resolve: {
alias: {
'@icons': path.resolve(__dirname, 'node_modules/@bm-fe/icons/svg'),
},
},
},
};PNG 国旗使用
国旗图标为 PNG 格式,不包装为组件,直接作为静态资源使用。
目录说明
| 目录 | 说明 |
|------|------|
| svg/flags/ | 原始 PNG 文件 |
| dist/flags/ | 压缩后的 PNG 文件(构建时生成,体积减少 67%+) |
生产环境建议使用 dist/flags/ 目录下的压缩文件。
静态导入
<template>
<img :src="cnFlag" alt="China" class="w-6 h-4" />
</template>
<script setup>
// 开发环境(原始文件)
import cnFlag from '@bm-fe/icons/svg/flags/cn.png';
// 生产环境(压缩文件,需配置构建)
// import cnFlag from '@bm-fe/icons/dist/flags/cn.png';
</script>动态导入(Vite)
// 批量导入所有国旗
const flagModules = import.meta.glob('@bm-fe/icons/svg/flags/*.png', {
eager: true,
import: 'default',
});
// 获取特定国旗
function getFlagUrl(countryCode: string): string {
const key = `/node_modules/@bm-fe/icons/svg/flags/${countryCode}.png`;
return flagModules[key] as string;
}
// 使用
const cnFlagUrl = getFlagUrl('cn');动态导入(Webpack)
// 使用 require.context
const flagContext = require.context(
'@bm-fe/icons/svg/flags',
false,
/\.png$/
);
function getFlagUrl(countryCode) {
return flagContext(`./${countryCode}.png`);
}图标分类
| 分类 | 目录 | 颜色策略 | 说明 |
|------|------|----------|------|
| Primary | svg/primary/ | currentColor | 基础 UI 图标,支持颜色继承 |
| Product | svg/product/ | currentColor | 产品图标,支持颜色继承 |
| Coin | svg/coin/ | 固定色 | 币种图标,保持原始颜色 |
| Currency | svg/currency/ | 固定色 | 货币符号,保持原始颜色 |
| Flags | svg/flags/ | PNG | 国旗图标,PNG 静态资源 |
颜色策略说明
- currentColor: 图标颜色继承父元素的
color属性,可通过 CSS 自定义颜色 - 固定色: 图标保持原始设计颜色,不支持颜色自定义
尺寸规范
推荐尺寸:12 | 16 | 20 | 24 | 32
也支持自定义 number | string 值。
开发
添加新图标
- 将 SVG 文件放入对应的分类目录(
svg/primary/,svg/product/, 等) - 文件名使用
kebab-case(如arrow-up.svg) - 运行
pnpm build生成组件
添加新国旗
- 将 PNG 文件放入
svg/flags/目录 - 文件名使用国家代码小写(如
cn.png,us.png) - 运行
pnpm build会自动压缩到dist/flags/
构建
pnpm build构建流程:
optimize:images- 压缩 PNG 国旗到dist/flags/generate:manifest- 扫描 SVG 目录,生成core/manifest.jsongenerate:react- 基于 manifest 生成 React 组件build:react- 构建 React 组件(生成 CJS/ESM 和类型定义)
目录结构
packages/icons/
├── svg/ # SVG/PNG 源文件(单一事实源)
│ ├── primary/ # Primary 图标
│ ├── product/ # Product 图标
│ ├── coin/ # Coin 图标
│ ├── currency/ # Currency 图标
│ └── flags/ # Flags PNG 静态资源
├── dist/
│ └── flags/ # 压缩后的 PNG 国旗
├── core/ # 核心层(manifest + 工具函数)
├── react/ # React 适配层
└── scripts/ # 生成器脚本约束
- ✅ SVG 作为单一事实源
- ✅ 生成器自动生成,禁止手改产物
- ✅ Primary/Product 支持
currentColor - ✅ Coin/Currency 使用固定色
- ✅ Flags 仅作为静态资源,不包装为组件
- ✅ PNG 自动压缩,生产环境使用压缩版
License
ISC
