Skip to content

Cache the converted element, not just the fetched text (picking #167 back up) #255

Description

@fastfrwrd

Hi @gilbarbara — reviving the second point of #167, with an implementation this time.

The cost

cacheRequests caches the SVG text, but nothing caches the result of converting it. useInlineSVG runs getNode() (a DOMParser parse) plus a DOM → React conversion on every mount, including on a cache hit — the lazy reducer initializer re-parses cached content. So the cost scales with the number of mounts, not with the number of distinct SVGs, and surfaces that mount icons constantly by design (virtualized tables, log lines, trees) pay it over and over.

Measured in Grafana, in a table panel with 300 rows and a handful of repeated icons: 600+ parses during ~25s of scrolling, resizing and hovering. Scrolling up and down mounted ~500 icons — all of them already in the request cache, all of them re-parsed.

The proposal

A cacheElements prop, off by default, that keeps the converted React element and reuses it. Same measurement afterwards: 4728 icon mounts → 2 conversions (one per distinct icon the session ever showed).

Design notes, since the size of the change was the concern last time (it is ~70 lines of src):

  • Entries are keyed by the content and by every prop that shapes the output: the preProcessor result, title (with undefined — keep an existing <title> — kept distinct from null — remove it), description, and for uniquifyIDs the hash and baseURL. Instances with random hashes therefore never share an entry; ones that pass the same uniqueHash do.
  • Module-level LRU capped at 100 elements, with a clearElementCache() export.
  • Nothing changes when the prop is not passed: no reads, no writes, no growth.
  • dist stays inside the existing 10 kB size limit (7.83 kB CJS / 7.29 kB ESM).

For context on the consumer side, this is the workaround we are thinking about adding in Grafana: grafana/grafana#132209 — we would much rather not, and use a library option instead.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions