Chore: update `react-inlinesvg` and use new icon caching mechanism (#97725)

* Update dependency react-inlinesvg to v4

* attempt to use new icon caching

* remove unicons chunk

* fix layout shift

* update snapshot

* parameterise cache by commit hash and clear old caches

* remove icon caching in storybook

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
pull/97846/head
Ashley Harrison 7 months ago committed by GitHub
parent 0a390cc069
commit b34fd6b6a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      .github/CODEOWNERS
  2. 3
      package.json
  3. 6
      packages/grafana-ui/.storybook/main.ts
  4. 1
      packages/grafana-ui/.storybook/storybookTheme.ts
  5. 3
      packages/grafana-ui/package.json
  6. 14
      packages/grafana-ui/src/components/Icon/Icon.tsx
  7. 55
      public/app/AppWrapper.tsx
  8. 2
      public/app/app.ts
  9. 395
      public/app/core/icons/iconBundle.ts
  10. 48
      public/app/core/icons/iconBundle.ts.template
  11. 5
      public/app/plugins/datasource/cloud-monitoring/components/__snapshots__/VariableQueryEditor.test.tsx.snap
  12. 1
      public/img/icons/README.md
  13. 5
      public/test/jest-setup.ts
  14. 51
      scripts/generate-icon-bundle.js
  15. 11
      scripts/webpack/webpack.common.js
  16. 32
      yarn.lock

@ -618,7 +618,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/scripts/trigger_windows_build.sh @grafana/grafana-developer-enablement-squad
/scripts/cleanup-husky.sh @grafana/frontend-ops
/scripts/verify-repo-update/ @grafana/grafana-developer-enablement-squad
/scripts/generate-icon-bundle.js @grafana/plugins-platform-frontend @grafana/grafana-frontend-platform
/scripts/generate-rtk-apis.ts @grafana/grafana-frontend-platform
/scripts/generate-alerting-rtk-apis.ts @grafana/alerting-frontend
/scripts/levitate-parse-json-report.js @grafana/plugins-platform-frontend

@ -59,7 +59,6 @@
"betterer:merge": "betterer merge --tsconfig ./scripts/cli/tsconfig.json",
"betterer:stats": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/reportBettererStats.ts",
"betterer:issues": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/generateBettererIssues.ts",
"generate-icons-bundle-cache-file": "node ./scripts/generate-icon-bundle.js",
"plugin:build": "nx run-many -t build --projects='tag:scope:plugin'",
"plugin:build:commit": "nx run-many -t build:commit --projects='tag:scope:plugin'",
"plugin:build:dev": "nx run-many -t dev --projects='tag:scope:plugin' --maxParallel=100",
@ -377,7 +376,7 @@
"react-highlight-words": "0.20.0",
"react-hook-form": "^7.49.2",
"react-i18next": "^14.0.0",
"react-inlinesvg": "3.0.2",
"react-inlinesvg": "4.1.5",
"react-loading-skeleton": "3.5.0",
"react-moveable": "0.56.0",
"react-redux": "9.1.2",

@ -87,12 +87,6 @@ const mainConfig: StorybookConfig = {
},
});
// use the asset module for SVGS for compatibility with grafana/ui Icon component.
config.module?.rules?.push({
test: /(unicons|mono|custom)[\\/].*\.svg$/,
type: 'asset/source',
});
return config;
},
};

@ -1,7 +1,6 @@
import { GrafanaTheme2, createTheme } from '@grafana/data';
//@ts-ignore
import { create } from '@storybook/theming';
import '../../../public/app/core/icons/iconBundle';
const createStorybookTheme = (theme: GrafanaTheme2) => {
return create({

@ -38,7 +38,6 @@
"storybook": "storybook dev -p 9001 -c .storybook --no-open",
"storybook:build": "storybook build -o ./dist/storybook -c .storybook",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"generate-icons-bundle-cache-file": "node ./scripts/generate-icon-bundle.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"postpack": "mv package.json.bak package.json"
},
@ -96,7 +95,7 @@
"react-highlight-words": "0.20.0",
"react-hook-form": "^7.49.2",
"react-i18next": "^14.0.0",
"react-inlinesvg": "3.0.2",
"react-inlinesvg": "4.1.5",
"react-loading-skeleton": "3.5.0",
"react-router-dom-v5-compat": "^6.26.1",
"react-select": "5.8.3",

@ -85,6 +85,20 @@ export const Icon = React.forwardRef<SVGElement, IconProps>(
title={title}
className={composedClassName}
style={style}
// render an empty div with the correct dimensions while loading
// this prevents content layout shift whilst the icon asynchronously loads
// which happens even if the icon is in the cache(!)
loader={
<div
className={cx(
css({
width: svgWid,
height: svgHgt,
}),
composedClassName
)}
/>
}
{...rest}
/>
);

@ -1,5 +1,6 @@
import { Action, KBarProvider } from 'kbar';
import { Component, ComponentType, Fragment } from 'react';
import CacheProvider from 'react-inlinesvg/provider';
import { Provider } from 'react-redux';
import { Route, Routes } from 'react-router-dom-v5-compat';
@ -46,6 +47,8 @@ export function addPageBanner(fn: ComponentType) {
}
export class AppWrapper extends Component<AppWrapperProps, AppWrapperState> {
private iconCacheID = `grafana-icon-cache-${config.buildInfo.commit}`;
constructor(props: AppWrapperProps) {
super(props);
this.state = {};
@ -55,6 +58,14 @@ export class AppWrapper extends Component<AppWrapperProps, AppWrapperState> {
await loadAndInitAngularIfEnabled();
this.setState({ ready: true });
$('.preloader').remove();
// clear any old icon caches
const cacheKeys = await window.caches.keys();
for (const key of cacheKeys) {
if (key.startsWith('grafana-icon-cache') && key !== this.iconCacheID) {
window.caches.delete(key);
}
}
}
renderRoute = (route: RouteDescriptor) => {
@ -98,27 +109,29 @@ export class AppWrapper extends Component<AppWrapperProps, AppWrapperState> {
<ErrorBoundaryAlert style="page">
<GrafanaContext.Provider value={app.context}>
<ThemeProvider value={config.theme2}>
<KBarProvider
actions={[]}
options={{ enableHistory: true, callbacks: { onSelectAction: commandPaletteActionSelected } }}
>
<GlobalStyles />
<MaybeTimeRangeProvider>
<SidecarContext_EXPERIMENTAL.Provider value={sidecarServiceSingleton_EXPERIMENTAL}>
<ExtensionRegistriesProvider registries={pluginExtensionRegistries}>
<div className="grafana-app">
{config.featureToggles.appSidecar ? (
<ExperimentalSplitPaneRouterWrapper {...routerWrapperProps} />
) : (
<RouterWrapper {...routerWrapperProps} />
)}
<LiveConnectionWarning />
<PortalContainer />
</div>
</ExtensionRegistriesProvider>
</SidecarContext_EXPERIMENTAL.Provider>
</MaybeTimeRangeProvider>
</KBarProvider>
<CacheProvider name={this.iconCacheID}>
<KBarProvider
actions={[]}
options={{ enableHistory: true, callbacks: { onSelectAction: commandPaletteActionSelected } }}
>
<GlobalStyles />
<MaybeTimeRangeProvider>
<SidecarContext_EXPERIMENTAL.Provider value={sidecarServiceSingleton_EXPERIMENTAL}>
<ExtensionRegistriesProvider registries={pluginExtensionRegistries}>
<div className="grafana-app">
{config.featureToggles.appSidecar ? (
<ExperimentalSplitPaneRouterWrapper {...routerWrapperProps} />
) : (
<RouterWrapper {...routerWrapperProps} />
)}
<LiveConnectionWarning />
<PortalContainer />
</div>
</ExtensionRegistriesProvider>
</SidecarContext_EXPERIMENTAL.Provider>
</MaybeTimeRangeProvider>
</KBarProvider>
</CacheProvider>
</ThemeProvider>
</GrafanaContext.Provider>
</ErrorBoundaryAlert>

@ -57,7 +57,6 @@ import { getAllOptionEditors, getAllStandardFieldConfigs } from './core/componen
import { PluginPage } from './core/components/Page/PluginPage';
import { GrafanaContextType, useChromeHeaderHeight, useReturnToPreviousInternal } from './core/context/GrafanaContext';
import { initializeCrashDetection } from './core/crash';
import { initIconCache } from './core/icons/iconBundle';
import { initializeI18n } from './core/internationalization';
import { setMonacoEnv } from './core/monacoEnv';
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks';
@ -138,7 +137,6 @@ export class GrafanaApp {
setBackendSrv(backendSrv);
initEchoSrv();
initIconCache();
// This needs to be done after the `initEchoSrv` since it is being used under the hood.
startMeasure('frontend_app_init');

@ -1,395 +0,0 @@
/* eslint-disable import/order */
// DO NOT EDIT THIS FILE
// This file is automatically generated (do not edit it here)
// see @grafana/ui/scripts/generate-icon-bundle.js
import { cacheStore } from 'react-inlinesvg';
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
import u1000 from '../../../img/icons/unicons/at.svg';
import u1001 from '../../../img/icons/unicons/adjust-circle.svg';
import u1002 from '../../../img/icons/unicons/align-left.svg';
import u1003 from '../../../img/icons/unicons/align-right.svg';
import u1004 from '../../../img/icons/unicons/angle-double-down.svg';
import u1005 from '../../../img/icons/unicons/angle-double-right.svg';
import u1006 from '../../../img/icons/unicons/angle-down.svg';
import u1007 from '../../../img/icons/unicons/angle-left.svg';
import u1008 from '../../../img/icons/unicons/angle-right.svg';
import u1009 from '../../../img/icons/unicons/angle-up.svg';
import u1010 from '../../../img/icons/unicons/apps.svg';
import u1011 from '../../../img/icons/unicons/arrow.svg';
import u1012 from '../../../img/icons/unicons/arrow-down.svg';
import u1013 from '../../../img/icons/unicons/arrow-from-right.svg';
import u1014 from '../../../img/icons/unicons/arrow-left.svg';
import u1015 from '../../../img/icons/unicons/arrow-random.svg';
import u1016 from '../../../img/icons/unicons/arrow-right.svg';
import u1017 from '../../../img/icons/unicons/arrow-to-right.svg';
import u1018 from '../../../img/icons/unicons/arrow-up.svg';
import u1019 from '../../../img/icons/unicons/arrows-h.svg';
import u1020 from '../../../img/icons/unicons/backward.svg';
import u1021 from '../../../img/icons/unicons/bars.svg';
import u1022 from '../../../img/icons/unicons/bell.svg';
import u1023 from '../../../img/icons/unicons/bell-slash.svg';
import u1024 from '../../../img/icons/unicons/bolt.svg';
import u1025 from '../../../img/icons/unicons/book.svg';
import u1026 from '../../../img/icons/unicons/bookmark.svg';
import u1027 from '../../../img/icons/unicons/book-open.svg';
import u1028 from '../../../img/icons/unicons/brackets-curly.svg';
import u1029 from '../../../img/icons/unicons/bug.svg';
import u1030 from '../../../img/icons/unicons/building.svg';
import u1031 from '../../../img/icons/unicons/calculator-alt.svg';
import u1032 from '../../../img/icons/unicons/calendar-alt.svg';
import u1033 from '../../../img/icons/unicons/calendar-slash.svg';
import u1034 from '../../../img/icons/unicons/camera.svg';
import u1035 from '../../../img/icons/unicons/channel-add.svg';
import u1036 from '../../../img/icons/unicons/chart-line.svg';
import u1037 from '../../../img/icons/unicons/check.svg';
import u1038 from '../../../img/icons/unicons/check-circle.svg';
import u1039 from '../../../img/icons/unicons/times-circle.svg';
import u1040 from '../../../img/icons/unicons/circle.svg';
import u1041 from '../../../img/icons/unicons/clipboard-alt.svg';
import u1042 from '../../../img/icons/unicons/clock-nine.svg';
import u1043 from '../../../img/icons/unicons/cloud.svg';
import u1044 from '../../../img/icons/unicons/cloud-download.svg';
import u1045 from '../../../img/icons/unicons/code-branch.svg';
import u1046 from '../../../img/icons/unicons/cog.svg';
import u1047 from '../../../img/icons/unicons/columns.svg';
import u1048 from '../../../img/icons/unicons/comment-alt.svg';
import u1049 from '../../../img/icons/unicons/comment-alt-share.svg';
import u1050 from '../../../img/icons/unicons/comments-alt.svg';
import u1051 from '../../../img/icons/unicons/compass.svg';
import u1052 from '../../../img/icons/unicons/copy.svg';
import u1053 from '../../../img/icons/unicons/corner-down-right-alt.svg';
import u1054 from '../../../img/icons/unicons/cube.svg';
import u1055 from '../../../img/icons/unicons/dashboard.svg';
import u1056 from '../../../img/icons/unicons/database.svg';
import u1057 from '../../../img/icons/unicons/document-info.svg';
import u1058 from '../../../img/icons/unicons/download-alt.svg';
import u1059 from '../../../img/icons/unicons/draggabledots.svg';
import u1060 from '../../../img/icons/unicons/edit.svg';
import u1061 from '../../../img/icons/unicons/ellipsis-v.svg';
import u1062 from '../../../img/icons/unicons/ellipsis-h.svg';
import u1063 from '../../../img/icons/unicons/envelope.svg';
import u1064 from '../../../img/icons/unicons/exchange-alt.svg';
import u1065 from '../../../img/icons/unicons/exclamation-circle.svg';
import u1066 from '../../../img/icons/unicons/exclamation-triangle.svg';
import u1067 from '../../../img/icons/unicons/external-link-alt.svg';
import u1068 from '../../../img/icons/unicons/eye.svg';
import u1069 from '../../../img/icons/unicons/eye-slash.svg';
import u1070 from '../../../img/icons/unicons/file-alt.svg';
import u1071 from '../../../img/icons/unicons/file-blank.svg';
import u1072 from '../../../img/icons/unicons/filter.svg';
import u1073 from '../../../img/icons/unicons/folder.svg';
import u1074 from '../../../img/icons/unicons/folder-open.svg';
import u1075 from '../../../img/icons/unicons/folder-plus.svg';
import u1076 from '../../../img/icons/unicons/folder-upload.svg';
import u1077 from '../../../img/icons/unicons/forward.svg';
import u1078 from '../../../img/icons/unicons/graph-bar.svg';
import u1079 from '../../../img/icons/unicons/history.svg';
import u1080 from '../../../img/icons/unicons/history-alt.svg';
import u1081 from '../../../img/icons/unicons/home-alt.svg';
import u1082 from '../../../img/icons/unicons/import.svg';
import u1083 from '../../../img/icons/unicons/info.svg';
import u1084 from '../../../img/icons/unicons/info-circle.svg';
import u1085 from '../../../img/icons/unicons/k6.svg';
import u1086 from '../../../img/icons/unicons/key-skeleton-alt.svg';
import u1087 from '../../../img/icons/unicons/keyboard.svg';
import u1088 from '../../../img/icons/unicons/link.svg';
import u1089 from '../../../img/icons/unicons/list-ul.svg';
import u1090 from '../../../img/icons/unicons/lock.svg';
import u1091 from '../../../img/icons/unicons/minus.svg';
import u1092 from '../../../img/icons/unicons/minus-circle.svg';
import u1093 from '../../../img/icons/unicons/mobile-android.svg';
import u1094 from '../../../img/icons/unicons/monitor.svg';
import u1095 from '../../../img/icons/unicons/pause.svg';
import u1096 from '../../../img/icons/unicons/pen.svg';
import u1097 from '../../../img/icons/unicons/play.svg';
import u1098 from '../../../img/icons/unicons/plug.svg';
import u1099 from '../../../img/icons/unicons/plus.svg';
import u1100 from '../../../img/icons/unicons/plus-circle.svg';
import u1101 from '../../../img/icons/unicons/power.svg';
import u1102 from '../../../img/icons/unicons/presentation-play.svg';
import u1103 from '../../../img/icons/unicons/process.svg';
import u1104 from '../../../img/icons/unicons/question-circle.svg';
import u1105 from '../../../img/icons/unicons/repeat.svg';
import u1106 from '../../../img/icons/unicons/rocket.svg';
import u1107 from '../../../img/icons/unicons/rss.svg';
import u1108 from '../../../img/icons/unicons/save.svg';
import u1109 from '../../../img/icons/unicons/search.svg';
import u1110 from '../../../img/icons/unicons/search-minus.svg';
import u1111 from '../../../img/icons/unicons/search-plus.svg';
import u1112 from '../../../img/icons/unicons/share-alt.svg';
import u1113 from '../../../img/icons/unicons/shield.svg';
import u1114 from '../../../img/icons/unicons/signal.svg';
import u1115 from '../../../img/icons/unicons/signin.svg';
import u1116 from '../../../img/icons/unicons/signout.svg';
import u1117 from '../../../img/icons/unicons/sitemap.svg';
import u1118 from '../../../img/icons/unicons/slack.svg';
import u1119 from '../../../img/icons/unicons/sliders-v-alt.svg';
import u1120 from '../../../img/icons/unicons/sort-amount-down.svg';
import u1121 from '../../../img/icons/unicons/sort-amount-up.svg';
import u1122 from '../../../img/icons/unicons/square-shape.svg';
import u1123 from '../../../img/icons/unicons/star.svg';
import u1124 from '../../../img/icons/unicons/step-backward.svg';
import u1125 from '../../../img/icons/unicons/sync.svg';
import u1126 from '../../../img/icons/unicons/stopwatch.svg';
import u1127 from '../../../img/icons/unicons/table.svg';
import u1128 from '../../../img/icons/unicons/tag-alt.svg';
import u1129 from '../../../img/icons/unicons/times.svg';
import u1130 from '../../../img/icons/unicons/trash-alt.svg';
import u1131 from '../../../img/icons/unicons/unlock.svg';
import u1132 from '../../../img/icons/unicons/upload.svg';
import u1133 from '../../../img/icons/unicons/user.svg';
import u1134 from '../../../img/icons/unicons/users-alt.svg';
import u1135 from '../../../img/icons/unicons/wrap-text.svg';
import u1136 from '../../../img/icons/unicons/cloud-upload.svg';
import u1137 from '../../../img/icons/unicons/credit-card.svg';
import u1138 from '../../../img/icons/unicons/file-copy-alt.svg';
import u1139 from '../../../img/icons/unicons/fire.svg';
import u1140 from '../../../img/icons/unicons/hourglass.svg';
import u1141 from '../../../img/icons/unicons/layer-group.svg';
import u1142 from '../../../img/icons/unicons/layers-alt.svg';
import u1143 from '../../../img/icons/unicons/line-alt.svg';
import u1144 from '../../../img/icons/unicons/list-ui-alt.svg';
import u1145 from '../../../img/icons/unicons/message.svg';
import u1146 from '../../../img/icons/unicons/palette.svg';
import u1147 from '../../../img/icons/unicons/percentage.svg';
import u1148 from '../../../img/icons/unicons/shield-exclamation.svg';
import u1149 from '../../../img/icons/unicons/plus-square.svg';
import u1150 from '../../../img/icons/unicons/x.svg';
import u1151 from '../../../img/icons/unicons/capture.svg';
import u1152 from '../../../img/icons/custom/gf-grid.svg';
import u1153 from '../../../img/icons/custom/gf-landscape.svg';
import u1154 from '../../../img/icons/custom/gf-layout-simple.svg';
import u1155 from '../../../img/icons/custom/gf-portrait.svg';
import u1156 from '../../../img/icons/custom/gf-show-context.svg';
import u1157 from '../../../img/icons/custom/gf-bar-alignment-after.svg';
import u1158 from '../../../img/icons/custom/gf-bar-alignment-before.svg';
import u1159 from '../../../img/icons/custom/gf-bar-alignment-center.svg';
import u1160 from '../../../img/icons/custom/gf-interpolation-linear.svg';
import u1161 from '../../../img/icons/custom/gf-interpolation-smooth.svg';
import u1162 from '../../../img/icons/custom/gf-interpolation-step-after.svg';
import u1163 from '../../../img/icons/custom/gf-interpolation-step-before.svg';
import u1164 from '../../../img/icons/custom/gf-logs.svg';
import u1165 from '../../../img/icons/custom/gf-movepane-left.svg';
import u1166 from '../../../img/icons/custom/gf-movepane-right.svg';
import u1167 from '../../../img/icons/mono/favorite.svg';
import u1168 from '../../../img/icons/mono/grafana.svg';
import u1169 from '../../../img/icons/mono/heart.svg';
import u1170 from '../../../img/icons/mono/heart-break.svg';
import u1171 from '../../../img/icons/mono/panel-add.svg';
import u1172 from '../../../img/icons/mono/library-panel.svg';
import u1173 from '../../../img/icons/unicons/record-audio.svg';
import u1174 from '../../../img/icons/solid/bookmark.svg';
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
let cacheInitialized = false;
function cacheItem(content: string, path: string) {
cacheStore[path] = { content, status: 'loaded' };
}
function createPathResolver() {
let root = 'public/img/icons/';
// This function needs to be called after index.js loads to give the
// application time to modify __webpack_public_path__ with a CDN path
const grafanaPublicPath = typeof window !== 'undefined' && window.__grafana_public_path__;
if (grafanaPublicPath) {
root = grafanaPublicPath + 'img/icons/';
}
return (path: string) => {
return root + path;
};
}
export function initIconCache() {
if (cacheInitialized) {
return;
}
cacheInitialized = true;
const resolvePath = createPathResolver();
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
cacheItem(u1000, resolvePath('unicons/at.svg'));
cacheItem(u1001, resolvePath('unicons/adjust-circle.svg'));
cacheItem(u1002, resolvePath('unicons/align-left.svg'));
cacheItem(u1003, resolvePath('unicons/align-right.svg'));
cacheItem(u1004, resolvePath('unicons/angle-double-down.svg'));
cacheItem(u1005, resolvePath('unicons/angle-double-right.svg'));
cacheItem(u1006, resolvePath('unicons/angle-down.svg'));
cacheItem(u1007, resolvePath('unicons/angle-left.svg'));
cacheItem(u1008, resolvePath('unicons/angle-right.svg'));
cacheItem(u1009, resolvePath('unicons/angle-up.svg'));
cacheItem(u1010, resolvePath('unicons/apps.svg'));
cacheItem(u1011, resolvePath('unicons/arrow.svg'));
cacheItem(u1012, resolvePath('unicons/arrow-down.svg'));
cacheItem(u1013, resolvePath('unicons/arrow-from-right.svg'));
cacheItem(u1014, resolvePath('unicons/arrow-left.svg'));
cacheItem(u1015, resolvePath('unicons/arrow-random.svg'));
cacheItem(u1016, resolvePath('unicons/arrow-right.svg'));
cacheItem(u1017, resolvePath('unicons/arrow-to-right.svg'));
cacheItem(u1018, resolvePath('unicons/arrow-up.svg'));
cacheItem(u1019, resolvePath('unicons/arrows-h.svg'));
cacheItem(u1020, resolvePath('unicons/backward.svg'));
cacheItem(u1021, resolvePath('unicons/bars.svg'));
cacheItem(u1022, resolvePath('unicons/bell.svg'));
cacheItem(u1023, resolvePath('unicons/bell-slash.svg'));
cacheItem(u1024, resolvePath('unicons/bolt.svg'));
cacheItem(u1025, resolvePath('unicons/book.svg'));
cacheItem(u1026, resolvePath('unicons/bookmark.svg'));
cacheItem(u1027, resolvePath('unicons/book-open.svg'));
cacheItem(u1028, resolvePath('unicons/brackets-curly.svg'));
cacheItem(u1029, resolvePath('unicons/bug.svg'));
cacheItem(u1030, resolvePath('unicons/building.svg'));
cacheItem(u1031, resolvePath('unicons/calculator-alt.svg'));
cacheItem(u1032, resolvePath('unicons/calendar-alt.svg'));
cacheItem(u1033, resolvePath('unicons/calendar-slash.svg'));
cacheItem(u1034, resolvePath('unicons/camera.svg'));
cacheItem(u1035, resolvePath('unicons/channel-add.svg'));
cacheItem(u1036, resolvePath('unicons/chart-line.svg'));
cacheItem(u1037, resolvePath('unicons/check.svg'));
cacheItem(u1038, resolvePath('unicons/check-circle.svg'));
cacheItem(u1039, resolvePath('unicons/times-circle.svg'));
cacheItem(u1040, resolvePath('unicons/circle.svg'));
cacheItem(u1041, resolvePath('unicons/clipboard-alt.svg'));
cacheItem(u1042, resolvePath('unicons/clock-nine.svg'));
cacheItem(u1043, resolvePath('unicons/cloud.svg'));
cacheItem(u1044, resolvePath('unicons/cloud-download.svg'));
cacheItem(u1045, resolvePath('unicons/code-branch.svg'));
cacheItem(u1046, resolvePath('unicons/cog.svg'));
cacheItem(u1047, resolvePath('unicons/columns.svg'));
cacheItem(u1048, resolvePath('unicons/comment-alt.svg'));
cacheItem(u1049, resolvePath('unicons/comment-alt-share.svg'));
cacheItem(u1050, resolvePath('unicons/comments-alt.svg'));
cacheItem(u1051, resolvePath('unicons/compass.svg'));
cacheItem(u1052, resolvePath('unicons/copy.svg'));
cacheItem(u1053, resolvePath('unicons/corner-down-right-alt.svg'));
cacheItem(u1054, resolvePath('unicons/cube.svg'));
cacheItem(u1055, resolvePath('unicons/dashboard.svg'));
cacheItem(u1056, resolvePath('unicons/database.svg'));
cacheItem(u1057, resolvePath('unicons/document-info.svg'));
cacheItem(u1058, resolvePath('unicons/download-alt.svg'));
cacheItem(u1059, resolvePath('unicons/draggabledots.svg'));
cacheItem(u1060, resolvePath('unicons/edit.svg'));
cacheItem(u1061, resolvePath('unicons/ellipsis-v.svg'));
cacheItem(u1062, resolvePath('unicons/ellipsis-h.svg'));
cacheItem(u1063, resolvePath('unicons/envelope.svg'));
cacheItem(u1064, resolvePath('unicons/exchange-alt.svg'));
cacheItem(u1065, resolvePath('unicons/exclamation-circle.svg'));
cacheItem(u1066, resolvePath('unicons/exclamation-triangle.svg'));
cacheItem(u1067, resolvePath('unicons/external-link-alt.svg'));
cacheItem(u1068, resolvePath('unicons/eye.svg'));
cacheItem(u1069, resolvePath('unicons/eye-slash.svg'));
cacheItem(u1070, resolvePath('unicons/file-alt.svg'));
cacheItem(u1071, resolvePath('unicons/file-blank.svg'));
cacheItem(u1072, resolvePath('unicons/filter.svg'));
cacheItem(u1073, resolvePath('unicons/folder.svg'));
cacheItem(u1074, resolvePath('unicons/folder-open.svg'));
cacheItem(u1075, resolvePath('unicons/folder-plus.svg'));
cacheItem(u1076, resolvePath('unicons/folder-upload.svg'));
cacheItem(u1077, resolvePath('unicons/forward.svg'));
cacheItem(u1078, resolvePath('unicons/graph-bar.svg'));
cacheItem(u1079, resolvePath('unicons/history.svg'));
cacheItem(u1080, resolvePath('unicons/history-alt.svg'));
cacheItem(u1081, resolvePath('unicons/home-alt.svg'));
cacheItem(u1082, resolvePath('unicons/import.svg'));
cacheItem(u1083, resolvePath('unicons/info.svg'));
cacheItem(u1084, resolvePath('unicons/info-circle.svg'));
cacheItem(u1085, resolvePath('unicons/k6.svg'));
cacheItem(u1086, resolvePath('unicons/key-skeleton-alt.svg'));
cacheItem(u1087, resolvePath('unicons/keyboard.svg'));
cacheItem(u1088, resolvePath('unicons/link.svg'));
cacheItem(u1089, resolvePath('unicons/list-ul.svg'));
cacheItem(u1090, resolvePath('unicons/lock.svg'));
cacheItem(u1091, resolvePath('unicons/minus.svg'));
cacheItem(u1092, resolvePath('unicons/minus-circle.svg'));
cacheItem(u1093, resolvePath('unicons/mobile-android.svg'));
cacheItem(u1094, resolvePath('unicons/monitor.svg'));
cacheItem(u1095, resolvePath('unicons/pause.svg'));
cacheItem(u1096, resolvePath('unicons/pen.svg'));
cacheItem(u1097, resolvePath('unicons/play.svg'));
cacheItem(u1098, resolvePath('unicons/plug.svg'));
cacheItem(u1099, resolvePath('unicons/plus.svg'));
cacheItem(u1100, resolvePath('unicons/plus-circle.svg'));
cacheItem(u1101, resolvePath('unicons/power.svg'));
cacheItem(u1102, resolvePath('unicons/presentation-play.svg'));
cacheItem(u1103, resolvePath('unicons/process.svg'));
cacheItem(u1104, resolvePath('unicons/question-circle.svg'));
cacheItem(u1105, resolvePath('unicons/repeat.svg'));
cacheItem(u1106, resolvePath('unicons/rocket.svg'));
cacheItem(u1107, resolvePath('unicons/rss.svg'));
cacheItem(u1108, resolvePath('unicons/save.svg'));
cacheItem(u1109, resolvePath('unicons/search.svg'));
cacheItem(u1110, resolvePath('unicons/search-minus.svg'));
cacheItem(u1111, resolvePath('unicons/search-plus.svg'));
cacheItem(u1112, resolvePath('unicons/share-alt.svg'));
cacheItem(u1113, resolvePath('unicons/shield.svg'));
cacheItem(u1114, resolvePath('unicons/signal.svg'));
cacheItem(u1115, resolvePath('unicons/signin.svg'));
cacheItem(u1116, resolvePath('unicons/signout.svg'));
cacheItem(u1117, resolvePath('unicons/sitemap.svg'));
cacheItem(u1118, resolvePath('unicons/slack.svg'));
cacheItem(u1119, resolvePath('unicons/sliders-v-alt.svg'));
cacheItem(u1120, resolvePath('unicons/sort-amount-down.svg'));
cacheItem(u1121, resolvePath('unicons/sort-amount-up.svg'));
cacheItem(u1122, resolvePath('unicons/square-shape.svg'));
cacheItem(u1123, resolvePath('unicons/star.svg'));
cacheItem(u1124, resolvePath('unicons/step-backward.svg'));
cacheItem(u1125, resolvePath('unicons/sync.svg'));
cacheItem(u1126, resolvePath('unicons/stopwatch.svg'));
cacheItem(u1127, resolvePath('unicons/table.svg'));
cacheItem(u1128, resolvePath('unicons/tag-alt.svg'));
cacheItem(u1129, resolvePath('unicons/times.svg'));
cacheItem(u1130, resolvePath('unicons/trash-alt.svg'));
cacheItem(u1131, resolvePath('unicons/unlock.svg'));
cacheItem(u1132, resolvePath('unicons/upload.svg'));
cacheItem(u1133, resolvePath('unicons/user.svg'));
cacheItem(u1134, resolvePath('unicons/users-alt.svg'));
cacheItem(u1135, resolvePath('unicons/wrap-text.svg'));
cacheItem(u1136, resolvePath('unicons/cloud-upload.svg'));
cacheItem(u1137, resolvePath('unicons/credit-card.svg'));
cacheItem(u1138, resolvePath('unicons/file-copy-alt.svg'));
cacheItem(u1139, resolvePath('unicons/fire.svg'));
cacheItem(u1140, resolvePath('unicons/hourglass.svg'));
cacheItem(u1141, resolvePath('unicons/layer-group.svg'));
cacheItem(u1142, resolvePath('unicons/layers-alt.svg'));
cacheItem(u1143, resolvePath('unicons/line-alt.svg'));
cacheItem(u1144, resolvePath('unicons/list-ui-alt.svg'));
cacheItem(u1145, resolvePath('unicons/message.svg'));
cacheItem(u1146, resolvePath('unicons/palette.svg'));
cacheItem(u1147, resolvePath('unicons/percentage.svg'));
cacheItem(u1148, resolvePath('unicons/shield-exclamation.svg'));
cacheItem(u1149, resolvePath('unicons/plus-square.svg'));
cacheItem(u1150, resolvePath('unicons/x.svg'));
cacheItem(u1151, resolvePath('unicons/capture.svg'));
cacheItem(u1152, resolvePath('custom/gf-grid.svg'));
cacheItem(u1153, resolvePath('custom/gf-landscape.svg'));
cacheItem(u1154, resolvePath('custom/gf-layout-simple.svg'));
cacheItem(u1155, resolvePath('custom/gf-portrait.svg'));
cacheItem(u1156, resolvePath('custom/gf-show-context.svg'));
cacheItem(u1157, resolvePath('custom/gf-bar-alignment-after.svg'));
cacheItem(u1158, resolvePath('custom/gf-bar-alignment-before.svg'));
cacheItem(u1159, resolvePath('custom/gf-bar-alignment-center.svg'));
cacheItem(u1160, resolvePath('custom/gf-interpolation-linear.svg'));
cacheItem(u1161, resolvePath('custom/gf-interpolation-smooth.svg'));
cacheItem(u1162, resolvePath('custom/gf-interpolation-step-after.svg'));
cacheItem(u1163, resolvePath('custom/gf-interpolation-step-before.svg'));
cacheItem(u1164, resolvePath('custom/gf-logs.svg'));
cacheItem(u1165, resolvePath('custom/gf-movepane-left.svg'));
cacheItem(u1166, resolvePath('custom/gf-movepane-right.svg'));
cacheItem(u1167, resolvePath('mono/favorite.svg'));
cacheItem(u1168, resolvePath('mono/grafana.svg'));
cacheItem(u1169, resolvePath('mono/heart.svg'));
cacheItem(u1170, resolvePath('mono/heart-break.svg'));
cacheItem(u1171, resolvePath('mono/panel-add.svg'));
cacheItem(u1172, resolvePath('mono/library-panel.svg'));
cacheItem(u1173, resolvePath('unicons/record-audio.svg'));
cacheItem(u1174, resolvePath('solid/bookmark.svg'));
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
}

@ -1,48 +0,0 @@
/* eslint-disable import/order */
// DO NOT EDIT THIS FILE
// This file is automatically generated (do not edit it here)
// see @grafana/ui/scripts/generate-icon-bundle.js
import { cacheStore } from 'react-inlinesvg';
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
//{{imports}}
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
let cacheInitialized = false;
function cacheItem(content: string, path: string) {
cacheStore[path] = { content, status: 'loaded' };
}
function createPathResolver() {
let root = 'public/img/icons/';
// This function needs to be called after index.js loads to give the
// application time to modify __webpack_public_path__ with a CDN path
const grafanaPublicPath = typeof window !== 'undefined' && window.__grafana_public_path__;
if (grafanaPublicPath) {
root = grafanaPublicPath + 'img/icons/';
}
return (path: string) => {
return root + path;
};
}
export function initIconCache() {
if (cacheInitialized) {
return;
}
cacheInitialized = true;
const resolvePath = createPathResolver();
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
//{{cacheItems}}
// do not edit this list directly
// the list of icons live here: @grafana/ui/components/Icon/cached.json
}

@ -95,6 +95,11 @@ exports[`VariableQueryEditor renders correctly 1`] = `
className="css-1d3xu67-Icon"
height={16}
id="public/img/icons/unicons/angle-down.svg"
loader={
<div
className="css-ua55tz-Icon"
/>
}
title=""
width={16}
/>

@ -3,6 +3,7 @@
- Add the new icon svg to the `unicons/` directory
- Yes, even if it's not a unicon icon or from [IconScout](https://iconscout.com/unicons/solid-icons)
- We will eventually condense all the separate folders into a single `icons/` directory, and since `unicons/` is the default it makes sense to add new icons there
- Add the new icon path to `public/app/core/icons/cached.json`
- Ensure the new icon source is formatted correctly:
- Remove any `width` or `height` attributes
- If the icon is a single color, ensure any explicitly defined fill or stroke colors are either removed (or set to `currentColor` if a color must be defined)

@ -8,7 +8,6 @@ import { TextEncoder, TextDecoder } from 'util';
import { EventBusSrv } from '@grafana/data';
import { GrafanaBootConfig } from '@grafana/runtime';
import { initIconCache } from 'app/core/icons/iconBundle';
import 'blob-polyfill';
import 'mutationobserver-shim';
@ -17,10 +16,6 @@ import './mocks/workers';
import '../vendor/flot/jquery.flot';
import '../vendor/flot/jquery.flot.time';
// icon cache needs to be initialized for test to prevent
// libraries such as msw from throwing "unhandled resource"-errors
initIconCache();
const testAppEvents = new EventBusSrv();
const global = window as any;
global.$ = global.jQuery = $;

@ -1,51 +0,0 @@
const fs = require('fs');
const os = require('os');
const path = require('path');
const cachedListPath = path.join(__dirname, '../public/app/core/icons/cached.json');
const iconsList = require(cachedListPath);
const iconsBundleJsTemplatePath = path.join(__dirname, '../public/app/core/icons/iconBundle.ts.template');
const iconsBundleJsPath = path.join(__dirname, '../public/app/core/icons/iconBundle.ts');
const iconsBundleJsTemplate = fs.readFileSync(iconsBundleJsTemplatePath).toString();
const importsStatements = [];
const cacheStatements = [];
const grafanaIconsPublicPath = '../../../img/icons/';
function generateIconBundle({ outputPath, verbose = false }) {
const modulePrefix = 'u';
let moduleNameCount = 1000;
for (iconEntry of iconsList) {
// skip empty and commented
if (iconEntry === '' || iconEntry.startsWith('#')) {
continue;
}
importsStatements.push(
`import ${modulePrefix}${moduleNameCount} from '${grafanaIconsPublicPath}${iconEntry}.svg';`
);
cacheStatements.push(` cacheItem(${modulePrefix}${moduleNameCount}, resolvePath('${iconEntry}.svg'));`);
moduleNameCount++;
}
const output = iconsBundleJsTemplate
.replace('//{{imports}}', importsStatements.join('\n'))
.replace('//{{cacheItems}}', cacheStatements.join('\n'));
fs.writeFileSync(outputPath, output);
if (verbose) {
console.log('The iconsBundle file was successfully written.');
console.log(`The file is located at ${outputPath}`);
}
return outputPath;
}
// if invoked directly
if (require.main === module) {
generateIconBundle({ outputPath: iconsBundleJsPath, verbose: true });
}
module.exports = generateIconBundle;

@ -105,11 +105,6 @@ module.exports = {
type: 'asset/resource',
generator: { filename: 'static/img/[name].[hash:8][ext]' },
},
// for pre-caching SVGs as part of the JS bundles
{
test: /(unicons|mono|custom|solid)[\\/].*\.svg$/,
type: 'asset/source',
},
{
// Required for msagl library (used in Nodegraph panel) to work
test: /\.m?js$/,
@ -126,12 +121,6 @@ module.exports = {
chunks: 'all',
minChunks: 1,
cacheGroups: {
unicons: {
test: /[\\/]node_modules[\\/]@iconscout[\\/]react-unicons[\\/].*[jt]sx?$/,
chunks: 'initial',
priority: 20,
enforce: true,
},
moment: {
test: /[\\/]node_modules[\\/]moment[\\/].*[jt]sx?$/,
chunks: 'initial',

@ -4012,7 +4012,7 @@ __metadata:
react-highlight-words: "npm:0.20.0"
react-hook-form: "npm:^7.49.2"
react-i18next: "npm:^14.0.0"
react-inlinesvg: "npm:3.0.2"
react-inlinesvg: "npm:4.1.5"
react-loading-skeleton: "npm:3.5.0"
react-router-dom-v5-compat: "npm:^6.26.1"
react-select: "npm:5.8.3"
@ -16211,13 +16211,6 @@ __metadata:
languageName: node
linkType: hard
"exenv@npm:^1.2.2":
version: 1.2.2
resolution: "exenv@npm:1.2.2"
checksum: 10/6840185e421394bcb143debb866d31d19c3e4a4bca87d2f319d68d61afff353b3c678f2eb389e3b98ab9aecbec19f6bebbdc4193984378af0a3366c498a7efc8
languageName: node
linkType: hard
"exit@npm:^0.1.2":
version: 0.1.2
resolution: "exit@npm:0.1.2"
@ -17833,7 +17826,7 @@ __metadata:
react-highlight-words: "npm:0.20.0"
react-hook-form: "npm:^7.49.2"
react-i18next: "npm:^14.0.0"
react-inlinesvg: "npm:3.0.2"
react-inlinesvg: "npm:4.1.5"
react-loading-skeleton: "npm:3.5.0"
react-moveable: "npm:0.56.0"
react-redux: "npm:9.1.2"
@ -25400,12 +25393,12 @@ __metadata:
languageName: node
linkType: hard
"react-from-dom@npm:^0.6.2":
version: 0.6.2
resolution: "react-from-dom@npm:0.6.2"
"react-from-dom@npm:^0.7.3":
version: 0.7.3
resolution: "react-from-dom@npm:0.7.3"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: 10/f3954737c2677e82f72ecedcdcf5f187d2a1b86a6c5b915f7300796ac153437581ee0111c9f524e7c18124d25d0d31391d54cdee318ea390722ca57e66813ed7
checksum: 10/55d6365af5b2aeaa0f2d80808dfa96114367e63849821b7ea277d193d4f6b1fce020e9754d4527ebc7f8628c5333f19dae38fc7b7956f69d5f640ac28b37ab0f
languageName: node
linkType: hard
@ -25514,15 +25507,14 @@ __metadata:
languageName: node
linkType: hard
"react-inlinesvg@npm:3.0.2":
version: 3.0.2
resolution: "react-inlinesvg@npm:3.0.2"
"react-inlinesvg@npm:4.1.5":
version: 4.1.5
resolution: "react-inlinesvg@npm:4.1.5"
dependencies:
exenv: "npm:^1.2.2"
react-from-dom: "npm:^0.6.2"
react-from-dom: "npm:^0.7.3"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: 10/740fa33c7a09012bb96509f9003dc26e4e412eed2fc861ca40bfee9a3dddcf7c4d86fd20f824d4c017e44526aa9d747d6c9543ef3f2215bc0ace72754e025316
react: 16.8 - 19
checksum: 10/475666855056007bfec56968d61793530f2089997d8a2956d603e03d9da8cd353a00368f220f07ef554c65feb4f5839112cefb2c84b22e511d8a470bea8eee61
languageName: node
linkType: hard

Loading…
Cancel
Save