Skip to content

refactor: bake the icon sprite locally instead of through svg-baker - #271

Merged
wenjianzhang merged 1 commit into
masterfrom
refactor/replace-svg-icons-plugin
Aug 27, 2026
Merged

refactor: bake the icon sprite locally instead of through svg-baker#271
wenjianzhang merged 1 commit into
masterfrom
refactor/replace-svg-icons-plugin

Conversation

@wenjianzhang

Copy link
Copy Markdown
Member

vite-plugin-svg-icons has not been published since 2022. Its sprite builder, svg-baker, carries thirteen direct dependencies — postcss 5, micromatch 3, image-size 0.5, loader-utils, bluebird among them. Those are the packages behind every advisory this repository has pinned through overrides, and none can be bumped: svg-baker's last release predates the fixes.

This removes the source instead of the symptom.

Most of what it does is unreachable here

svg-baker's central mechanism is renaming ids and prefixing classes so that combined files cannot collide. Nothing in src/icons/svg refers to an id:

url(#…)      0 occurrences across 128 files
href="#…"    0 occurrences

The 83 ids that are present (Capa_1, 4698, 972) are drawing-tool leftovers, which svgo strips. That machinery has been running on every build for nothing.

Three things that do matter

build/svg-sprite.mjs reproduces each:

  1. Strip the wrapper's attributes — one file's class="icon" or stray <style> must not leak onto the others.
  2. Derive a viewBox for the 43 icons that carry only width and height. A <symbol> without one does not scale.
  3. Keep ids as icon-<filename> — the contract SvgIcon reads when it renders <use href="#icon-{iconClass}">.

The second was the surprise, and the reason this was probed before it was written. Those viewBoxes are not in the source files — svg-baker computes them from width/height:

404.svg:     <svg width="128" height="128" xmlns=…>          ← no viewBox
add-db.svg:  <svg … viewBox="0 0 1024 1024" …>               ← has one

An implementation that skipped that step would have deformed a third of the icon set while every existing test still passed.

Cleaning is svgo 4, which this repository already depends on and already runs over these files through the svgo script. No new dependency.

Verified against a captured baseline

The old plugin's sprite was captured from a running page before the swap, then compared symbol by symbol after:

before after
symbols 128 128
ids missing / added 0 / 0
viewBox differences 0
element-structure differences 0

tests/e2e/mocked/app-shell.spec.ts already guards the failure this must not have — a missing sprite leaves every <use> in the DOM and every test green while the sidebar renders blank squares. It passes.

Two of three overrides go with it

postcss@5.2.18, micromatch@3.1.0 and braces@2.3.2 are gone from the lockfile entirely — they came in through svg-baker, and everything now resolves to current versions on its own. Removing the pins and reinstalling confirms it.

The glob pin stays: its source is @vue/test-utils → js-beautify, unrelated to this.

 "overrides": {
-  "postcss@<8.4.31": ">=8.4.31",
-  "braces@<3.0.3": ">=3.0.3",
   "glob@<10.5.0": ">=10.5.0"
 }

Verification

lint 0 errors (29 pre-existing warnings) · type-check clean · unit 220 · e2e 143 · build:prod ok · net −1646 lines.

@wenjianzhang
wenjianzhang force-pushed the refactor/replace-svg-icons-plugin branch from 7f060e7 to 2598e4a Compare August 27, 2026 07:47
vite-plugin-svg-icons has not been published since 2022, and its sprite
builder, svg-baker, carries thirteen direct dependencies of its own --
postcss 5, micromatch 3, image-size 0.5 among them. Those are the
packages behind every advisory this repository has had to pin through
overrides, and none can be bumped: svg-baker's last release predates the
fixes. Replacing the plugin removes the source rather than the symptom.

Most of what svg-baker does is unreachable here. Its central mechanism is
renaming ids and prefixing classes so combined files cannot collide --
and nothing in src/icons/svg refers to an id: `url(#…)` and `href="#…"`
appear zero times across all 128 files. The ids present (`Capa_1`,
`4698`) are drawing-tool leftovers, which svgo removes.

Three things it does matter, and build/svg-sprite.mjs does each:

  1. strip the wrapper's attributes, so one file's `class="icon"` or
     stray <style> cannot leak onto the others;
  2. derive a viewBox for the 43 icons that carry only width and height.
     A <symbol> without one does not scale. This was the surprise --
     those viewBoxes are not in the source files, svg-baker computes
     them, and an implementation that skipped this step would have
     deformed a third of the set while every existing test passed;
  3. keep ids as `icon-<filename>`, the contract SvgIcon reads when it
     renders `<use href="#icon-{iconClass}">`.

Cleaning is svgo 4, which the repository already depends on and already
runs over these files through the `svgo` script.

Verified against a sprite captured from the old plugin before the swap:
128 symbols before, 128 after, no id missing or added, no viewBox
different, no element structure different.

Two of the three pnpm overrides go with it. postcss and braces came in
through svg-baker and resolve to current versions on their own now; the
glob one stays, its source is @vue/test-utils -> js-beautify.
@wenjianzhang
wenjianzhang force-pushed the refactor/replace-svg-icons-plugin branch from 2598e4a to 41ba46a Compare August 27, 2026 09:37
@wenjianzhang
wenjianzhang merged commit e6e3995 into master Aug 27, 2026
5 checks passed
@wenjianzhang
wenjianzhang deleted the refactor/replace-svg-icons-plugin branch August 27, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant