gilbarbara / gilbarbara/react-inlinesvg
Cache the converted element, not just the fetched text (picking #167 back up)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.3k
- Forks
- 105
- PR merge metrics
- No merged PRs in 30d
Description
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
preProcessorresult,title(withundefined— keep an existing<title>— kept distinct fromnull— remove it),description, and foruniquifyIDsthe hash andbaseURL. Instances with random hashes therefore never share an entry; ones that pass the sameuniqueHashdo. - 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.
diststays 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: https://github.com/grafana/grafana/pull/132209 — we would much rather not, and use a library option instead.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in the src implementation of useInlineSVG and its existing cacheRequests/getNode path to trace where cached SVG text becomes a React element. Done means an opt-in cache reuses converted elements with the specified keys, LRU limit, and clearElementCache export, while the default behavior is unchanged and dist remains within the stated size limit.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 62/100