Commit 38c71a81d610b4a48eeadc13dbc85cdac4fccddd
Merge branch 'perf/offline-icon' into 'main'
perf: 使用离线Icon图标 See merge request yunteng/thingskit-front!1497
Showing
6 changed files
with
248 additions
and
1 deletions
build/generate/iconfont/offline.icon.ts
0 → 100644
1 | +import { IconifyJSON } from '@iconify/iconify'; | |
2 | +import { camelCase } from 'lodash-es'; | |
3 | + | |
4 | +interface IconType { | |
5 | + prefix: string; | |
6 | + icon: string; | |
7 | + alias?: string; | |
8 | +} | |
9 | + | |
10 | +export function getCacheIcons() { | |
11 | + const storageKeys = Object.keys(localStorage); | |
12 | + | |
13 | + const iconifyKeys = storageKeys.filter((key) => key.startsWith('iconify')); | |
14 | + | |
15 | + const allIcons: IconType[] = []; | |
16 | + for (const key of iconifyKeys) { | |
17 | + try { | |
18 | + const res: Record<'data', IconifyJSON> = JSON.parse(localStorage.getItem(key)!); | |
19 | + | |
20 | + const { | |
21 | + data: { prefix, icons, aliases }, | |
22 | + } = res; | |
23 | + | |
24 | + allIcons.push(...Object.keys(icons).map((icon) => ({ icon, prefix }))); | |
25 | + | |
26 | + allIcons.push( | |
27 | + ...Object.entries(aliases || {}).map(([key, value]) => ({ | |
28 | + icon: key, | |
29 | + alias: value.parent, | |
30 | + prefix, | |
31 | + })) | |
32 | + ); | |
33 | + } catch { | |
34 | + continue; | |
35 | + } | |
36 | + } | |
37 | + | |
38 | + const collect = allIcons.reduce((prev, next) => { | |
39 | + if (Reflect.has(prev, next.prefix)) { | |
40 | + prev[next.prefix].push(next); | |
41 | + } else { | |
42 | + prev[next.prefix] = [next]; | |
43 | + } | |
44 | + return prev; | |
45 | + }, {} as Record<string, IconType[]>); | |
46 | + | |
47 | + const icons = Object.entries(collect).reduce( | |
48 | + (prev, [key, value]) => { | |
49 | + for (const { icon, alias } of value) { | |
50 | + const importName = camelCase(`${key}-${alias || icon}`); | |
51 | + | |
52 | + prev.imports.push( | |
53 | + `import ${importName} from 'virtual:@iconify/json/${key}/${alias || icon}';` | |
54 | + ); | |
55 | + | |
56 | + prev.registerIcons.push(`addIcon('${key}:${icon}', ${importName});`); | |
57 | + } | |
58 | + | |
59 | + return prev; | |
60 | + }, | |
61 | + { imports: [], registerIcons: [] } as Record<'imports' | 'registerIcons', string[]> | |
62 | + ); | |
63 | + | |
64 | + return `${[...new Set(icons.imports)].join('\n')}\n${[...new Set(icons.registerIcons)].join( | |
65 | + '\n' | |
66 | + )}`; | |
67 | +} | ... | ... |
build/vite/plugin/iconify.ts
0 → 100644
1 | +import { existsSync, readFileSync } from 'fs'; | |
2 | +import { Plugin } from 'vite'; | |
3 | +import { IconifyJSON } from '@iconify/iconify'; | |
4 | + | |
5 | +const Plugin_Name = '@iconify-icon-offline-import'; | |
6 | + | |
7 | +const baseMsg = (msg: string) => `[${Plugin_Name}] ${msg}`; | |
8 | + | |
9 | +export default function IconifyPlugin(): Plugin { | |
10 | + const virtualModuleId = 'virtual:@iconify/json'; | |
11 | + | |
12 | + const cache: Record<string, IconifyJSON> = {}; | |
13 | + | |
14 | + return { | |
15 | + name: 'iconify-json-tree-sharking', | |
16 | + resolveId(id) { | |
17 | + if (id.includes(virtualModuleId)) { | |
18 | + return '\0' + id; | |
19 | + } | |
20 | + }, | |
21 | + async load(id) { | |
22 | + if (id.includes(virtualModuleId)) { | |
23 | + const iconPaths = id.split(virtualModuleId); | |
24 | + const iconPath = iconPaths[iconPaths.length - 1]; | |
25 | + | |
26 | + if (!iconPath) return 'export default {}'; | |
27 | + | |
28 | + const [collectName, iconName] = iconPath.split('/').filter(Boolean); | |
29 | + | |
30 | + const collectPath = require.resolve(`@iconify/json/json/${collectName}.json`); | |
31 | + | |
32 | + if (!existsSync(collectPath)) { | |
33 | + const msg = baseMsg(`Can't found virtual:@iconify/json/${collectName}/${iconName}.`); | |
34 | + throw new Error(msg); | |
35 | + } | |
36 | + | |
37 | + let collect: IconifyJSON; | |
38 | + if (cache[collectName]) { | |
39 | + collect = cache[collectName]; | |
40 | + } else { | |
41 | + const res = readFileSync(collectPath, { | |
42 | + encoding: 'utf-8', | |
43 | + }); | |
44 | + collect = JSON.parse(res); | |
45 | + cache[collectName] = collect; | |
46 | + } | |
47 | + | |
48 | + if (Object.hasOwn(collect.icons, iconName)) { | |
49 | + return `export default ${JSON.stringify( | |
50 | + Object.assign(collect.icons[iconName], { | |
51 | + width: collect.width, | |
52 | + height: collect.height, | |
53 | + }), | |
54 | + null, | |
55 | + 2 | |
56 | + )}`; | |
57 | + } else { | |
58 | + const msg = baseMsg(`Can't found ${iconName} from ${collectName} collect.`); | |
59 | + throw new Error(msg); | |
60 | + } | |
61 | + } | |
62 | + }, | |
63 | + }; | |
64 | +} | ... | ... |
... | ... | @@ -16,6 +16,7 @@ import { configThemePlugin } from './theme'; |
16 | 16 | import { configImageminPlugin } from './imagemin'; |
17 | 17 | import { configSvgIconsPlugin } from './svgSprite'; |
18 | 18 | import { configHmrPlugin } from './hmr'; |
19 | +import IconifyPlugin from './iconify'; | |
19 | 20 | |
20 | 21 | export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { |
21 | 22 | const { |
... | ... | @@ -77,5 +78,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { |
77 | 78 | vitePlugins.push(configPwaConfig(viteEnv)); |
78 | 79 | } |
79 | 80 | |
81 | + vitePlugins.push(IconifyPlugin()); | |
80 | 82 | return vitePlugins; |
81 | 83 | } | ... | ... |
... | ... | @@ -87,7 +87,7 @@ |
87 | 87 | "devDependencies": { |
88 | 88 | "@commitlint/cli": "^13.1.0", |
89 | 89 | "@commitlint/config-conventional": "^13.1.0", |
90 | - "@iconify/json": "^1.1.386", | |
90 | + "@iconify/json": "^2.2.257", | |
91 | 91 | "@purge-icons/generated": "^0.7.0", |
92 | 92 | "@types/codemirror": "^5.60.2", |
93 | 93 | "@types/crypto-js": "^4.0.2", | ... | ... |
src/components/Icon/data/offline.icon.ts
0 → 100644
1 | +import antDesignGoldOutlined from 'virtual:@iconify/json/ant-design/gold-outlined'; | |
2 | +import antDesignHomeOutlined from 'virtual:@iconify/json/ant-design/home-outlined'; | |
3 | +import antDesignIssuesCloseOutlined from 'virtual:@iconify/json/ant-design/issues-close-outlined'; | |
4 | +import antDesignMacCommandOutlined from 'virtual:@iconify/json/ant-design/mac-command-outlined'; | |
5 | +import antDesignMessageOutlined from 'virtual:@iconify/json/ant-design/message-outlined'; | |
6 | +import antDesignMobileOutlined from 'virtual:@iconify/json/ant-design/mobile-outlined'; | |
7 | +import antDesignNotificationOutlined from 'virtual:@iconify/json/ant-design/notification-outlined'; | |
8 | +import antDesignPieChartOutlined from 'virtual:@iconify/json/ant-design/pie-chart-outlined'; | |
9 | +import antDesignProjectOutlined from 'virtual:@iconify/json/ant-design/project-outlined'; | |
10 | +import antDesignProjectTwotone from 'virtual:@iconify/json/ant-design/project-twotone'; | |
11 | +import antDesignReconciliationOutlined from 'virtual:@iconify/json/ant-design/reconciliation-outlined'; | |
12 | +import antDesignSelectOutlined from 'virtual:@iconify/json/ant-design/select-outlined'; | |
13 | +import antDesignShoppingOutlined from 'virtual:@iconify/json/ant-design/shopping-outlined'; | |
14 | +import antDesignSoundOutlined from 'virtual:@iconify/json/ant-design/sound-outlined'; | |
15 | +import antDesignSwapOutlined from 'virtual:@iconify/json/ant-design/swap-outlined'; | |
16 | +import antDesignTagsOutlined from 'virtual:@iconify/json/ant-design/tags-outlined'; | |
17 | +import antDesignUngroupOutlined from 'virtual:@iconify/json/ant-design/ungroup-outlined'; | |
18 | +import antDesignVideoCameraAddOutlined from 'virtual:@iconify/json/ant-design/video-camera-add-outlined'; | |
19 | +import antDesignVideoCameraOutlined from 'virtual:@iconify/json/ant-design/video-camera-outlined'; | |
20 | +import antDesignAlertOutlined from 'virtual:@iconify/json/ant-design/alert-outlined'; | |
21 | +import antDesignAliyunOutlined from 'virtual:@iconify/json/ant-design/aliyun-outlined'; | |
22 | +import antDesignBarChartOutlined from 'virtual:@iconify/json/ant-design/bar-chart-outlined'; | |
23 | +import antDesignBookTwotone from 'virtual:@iconify/json/ant-design/book-twotone'; | |
24 | +import antDesignBorderBottomOutlined from 'virtual:@iconify/json/ant-design/border-bottom-outlined'; | |
25 | +import antDesignBorderOuterOutlined from 'virtual:@iconify/json/ant-design/border-outer-outlined'; | |
26 | +import antDesignBranchesOutlined from 'virtual:@iconify/json/ant-design/branches-outlined'; | |
27 | +import antDesignCalculatorTwotone from 'virtual:@iconify/json/ant-design/calculator-twotone'; | |
28 | +import antDesignCalendarFilled from 'virtual:@iconify/json/ant-design/calendar-filled'; | |
29 | +import antDesignCloudServerOutlined from 'virtual:@iconify/json/ant-design/cloud-server-outlined'; | |
30 | +import antDesignCodeOutlined from 'virtual:@iconify/json/ant-design/code-outlined'; | |
31 | +import antDesignContactsOutlined from 'virtual:@iconify/json/ant-design/contacts-outlined'; | |
32 | +import antDesignContainerOutlined from 'virtual:@iconify/json/ant-design/container-outlined'; | |
33 | +import antDesignContainerTwotone from 'virtual:@iconify/json/ant-design/container-twotone'; | |
34 | +import antDesignCopyTwotone from 'virtual:@iconify/json/ant-design/copy-twotone'; | |
35 | +import antDesignDashboardOutlined from 'virtual:@iconify/json/ant-design/dashboard-outlined'; | |
36 | +import antDesignDeploymentUnitOutlined from 'virtual:@iconify/json/ant-design/deployment-unit-outlined'; | |
37 | +import antDesignEnvironmentOutlined from 'virtual:@iconify/json/ant-design/environment-outlined'; | |
38 | +import antDesignExceptionOutlined from 'virtual:@iconify/json/ant-design/exception-outlined'; | |
39 | +import antDesignFileAddOutlined from 'virtual:@iconify/json/ant-design/file-add-outlined'; | |
40 | +import antDesignFileDoneOutlined from 'virtual:@iconify/json/ant-design/file-done-outlined'; | |
41 | +import antDesignFileMarkdownOutlined from 'virtual:@iconify/json/ant-design/file-markdown-outlined'; | |
42 | +import antDesignFilePptOutlined from 'virtual:@iconify/json/ant-design/file-ppt-outlined'; | |
43 | +import antDesignFileTextOutlined from 'virtual:@iconify/json/ant-design/file-text-outlined'; | |
44 | +import materialSymbolsCallMade from 'virtual:@iconify/json/material-symbols/call-made'; | |
45 | +import materialSymbolsUpload from 'virtual:@iconify/json/material-symbols/upload'; | |
46 | +import materialSymbolsInputSharp from 'virtual:@iconify/json/material-symbols/input-sharp'; | |
47 | +import materialSymbolsMenu from 'virtual:@iconify/json/material-symbols/menu'; | |
48 | +import materialSymbolsSms from 'virtual:@iconify/json/material-symbols/sms'; | |
49 | +import materialSymbolsBackup from 'virtual:@iconify/json/material-symbols/backup'; | |
50 | +import materialSymbolsFilterList from 'virtual:@iconify/json/material-symbols/filter-list'; | |
51 | +import materialSymbolsFlashOn from 'virtual:@iconify/json/material-symbols/flash-on'; | |
52 | +import materialSymbolsSearch from 'virtual:@iconify/json/material-symbols/search'; | |
53 | +import materialSymbolsSettingsEthernet from 'virtual:@iconify/json/material-symbols/settings-ethernet'; | |
54 | +import mdiCheck from 'virtual:@iconify/json/mdi/check'; | |
55 | +import { addIcon } from '@iconify/iconify'; | |
56 | + | |
57 | +addIcon('ant-design:gold-outlined', antDesignGoldOutlined); | |
58 | +addIcon('ant-design:home-outlined', antDesignHomeOutlined); | |
59 | +addIcon('ant-design:issues-close-outlined', antDesignIssuesCloseOutlined); | |
60 | +addIcon('ant-design:mac-command-outlined', antDesignMacCommandOutlined); | |
61 | +addIcon('ant-design:message-outlined', antDesignMessageOutlined); | |
62 | +addIcon('ant-design:mobile-outlined', antDesignMobileOutlined); | |
63 | +addIcon('ant-design:notification-outlined', antDesignNotificationOutlined); | |
64 | +addIcon('ant-design:pie-chart-outlined', antDesignPieChartOutlined); | |
65 | +addIcon('ant-design:project-outlined', antDesignProjectOutlined); | |
66 | +addIcon('ant-design:project-twotone', antDesignProjectTwotone); | |
67 | +addIcon('ant-design:reconciliation-outlined', antDesignReconciliationOutlined); | |
68 | +addIcon('ant-design:select-outlined', antDesignSelectOutlined); | |
69 | +addIcon('ant-design:shopping-outlined', antDesignShoppingOutlined); | |
70 | +addIcon('ant-design:sound-outlined', antDesignSoundOutlined); | |
71 | +addIcon('ant-design:swap-outlined', antDesignSwapOutlined); | |
72 | +addIcon('ant-design:tags-outlined', antDesignTagsOutlined); | |
73 | +addIcon('ant-design:ungroup-outlined', antDesignUngroupOutlined); | |
74 | +addIcon('ant-design:video-camera-add-outlined', antDesignVideoCameraAddOutlined); | |
75 | +addIcon('ant-design:video-camera-outlined', antDesignVideoCameraOutlined); | |
76 | +addIcon('ant-design:alert-outlined', antDesignAlertOutlined); | |
77 | +addIcon('ant-design:aliyun-outlined', antDesignAliyunOutlined); | |
78 | +addIcon('ant-design:bar-chart-outlined', antDesignBarChartOutlined); | |
79 | +addIcon('ant-design:book-twotone', antDesignBookTwotone); | |
80 | +addIcon('ant-design:border-bottom-outlined', antDesignBorderBottomOutlined); | |
81 | +addIcon('ant-design:border-outer-outlined', antDesignBorderOuterOutlined); | |
82 | +addIcon('ant-design:branches-outlined', antDesignBranchesOutlined); | |
83 | +addIcon('ant-design:calculator-twotone', antDesignCalculatorTwotone); | |
84 | +addIcon('ant-design:calendar-filled', antDesignCalendarFilled); | |
85 | +addIcon('ant-design:cloud-server-outlined', antDesignCloudServerOutlined); | |
86 | +addIcon('ant-design:code-outlined', antDesignCodeOutlined); | |
87 | +addIcon('ant-design:contacts-outlined', antDesignContactsOutlined); | |
88 | +addIcon('ant-design:container-outlined', antDesignContainerOutlined); | |
89 | +addIcon('ant-design:container-twotone', antDesignContainerTwotone); | |
90 | +addIcon('ant-design:copy-twotone', antDesignCopyTwotone); | |
91 | +addIcon('ant-design:dashboard-outlined', antDesignDashboardOutlined); | |
92 | +addIcon('ant-design:deployment-unit-outlined', antDesignDeploymentUnitOutlined); | |
93 | +addIcon('ant-design:environment-outlined', antDesignEnvironmentOutlined); | |
94 | +addIcon('ant-design:exception-outlined', antDesignExceptionOutlined); | |
95 | +addIcon('ant-design:file-add-outlined', antDesignFileAddOutlined); | |
96 | +addIcon('ant-design:file-done-outlined', antDesignFileDoneOutlined); | |
97 | +addIcon('ant-design:file-markdown-outlined', antDesignFileMarkdownOutlined); | |
98 | +addIcon('ant-design:file-ppt-outlined', antDesignFilePptOutlined); | |
99 | +addIcon('ant-design:file-text-outlined', antDesignFileTextOutlined); | |
100 | +addIcon('material-symbols:call-made', materialSymbolsCallMade); | |
101 | +addIcon('material-symbols:upload', materialSymbolsUpload); | |
102 | +addIcon('material-symbols:input-sharp', materialSymbolsInputSharp); | |
103 | +addIcon('material-symbols:menu', materialSymbolsMenu); | |
104 | +addIcon('material-symbols:sms', materialSymbolsSms); | |
105 | +addIcon('material-symbols:file-upload', materialSymbolsUpload); | |
106 | +addIcon('material-symbols:backup', materialSymbolsBackup); | |
107 | +addIcon('material-symbols:filter-list', materialSymbolsFilterList); | |
108 | +addIcon('material-symbols:flash-on', materialSymbolsFlashOn); | |
109 | +addIcon('material-symbols:search', materialSymbolsSearch); | |
110 | +addIcon('material-symbols:settings-ethernet', materialSymbolsSettingsEthernet); | |
111 | +addIcon('material-symbols:cloud-upload', materialSymbolsBackup); | |
112 | +addIcon('mdi:check', mdiCheck); | |
113 | +addIcon('mdi:tick', mdiCheck); | ... | ... |