Commit 38c71a81d610b4a48eeadc13dbc85cdac4fccddd

Authored by xp.Huang
2 parents ca2665aa 15b42954

Merge branch 'perf/offline-icon' into 'main'

perf: 使用离线Icon图标

See merge request yunteng/thingskit-front!1497
  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 +}
... ...
  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",
... ...
  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);
... ...
1 1 import Icon from './src/Icon.vue';
2 2 import SvgIcon from './src/SvgIcon.vue';
3 3 import IconPicker from './src/IconPicker.vue';
  4 +import './data/offline.icon';
4 5
5 6 export { Icon, IconPicker, SvgIcon };
6 7
... ...