From 463c6ba1f0403aa25605fd363ac863159ee4c492 Mon Sep 17 00:00:00 2001 From: Tremayne Christ Date: Fri, 22 Oct 2021 16:35:17 +0100 Subject: [PATCH] perf(icon): cache svg template results --- packages/elements/src/icon/index.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/elements/src/icon/index.ts b/packages/elements/src/icon/index.ts index 301a470981..09c4d91768 100644 --- a/packages/elements/src/icon/index.ts +++ b/packages/elements/src/icon/index.ts @@ -7,6 +7,7 @@ import { CSSResult, unsafeHTML, TemplateResult, + SVGTemplateResult, PropertyValues } from '@refinitiv-ui/core'; import { VERSION } from '../'; @@ -15,6 +16,13 @@ export { preload } from './utils/IconLoader'; const EmptyTemplate = svg``; +/** + * Cache for reusing SVG template results across multiple icons. + * Reusing these templates increases performance dramatically when many icons are rendered. + * As the cache key is an absolute URL, we can assume no clashes will occur. + */ +const iconTemplateCache = new Map>(); + @customElement('ef-icon', { alias: 'coral-icon' }) @@ -133,10 +141,16 @@ export class Icon extends BasicElement { * @returns {void} */ private async loadAndRenderIcon (src: string): Promise { - const svgBody = await IconLoader.loadSVG(src); - if (svgBody) { - this.template = svg`${unsafeHTML(svgBody)}`; + const iconTemplateCacheItem = iconTemplateCache.get(src); + if (!iconTemplateCacheItem) { + iconTemplateCache.set( + src, + IconLoader.loadSVG(src) + .then(body => svg`${unsafeHTML(body)}`) + ); + return this.loadAndRenderIcon(src); // Load again and await cache result } + this.template = await iconTemplateCacheItem; } /**