Skip to content

Commit

Permalink
perf(icon): cache svg template results
Browse files Browse the repository at this point in the history
  • Loading branch information
TremayneChrist committed Oct 22, 2021
1 parent 6d3a92d commit 463c6ba
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions packages/elements/src/icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
CSSResult,
unsafeHTML,
TemplateResult,
SVGTemplateResult,
PropertyValues
} from '@refinitiv-ui/core';
import { VERSION } from '../';
Expand All @@ -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<string, Promise<SVGTemplateResult>>();

@customElement('ef-icon', {
alias: 'coral-icon'
})
Expand Down Expand Up @@ -133,10 +141,16 @@ export class Icon extends BasicElement {
* @returns {void}
*/
private async loadAndRenderIcon (src: string): Promise<void> {
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;
}

/**
Expand Down

0 comments on commit 463c6ba

Please sign in to comment.