ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 49

  1. Blog

SVGO vs SVGR: 34ms / 35% Smaller SVG Set

svgo 4.1.0 vs @svgr/core 8.1.0 on 20 verbose 128×128 SVGs (18,990 B). Warm medians (7 rounds after 1 warm-up): SVGO 34 ms / 12,410 B; SVGR JSX 35 ms / 17,620 B; SVGR+plugin-svgo 63 ms / 12,920 B. Fixture /workspace/bench-svgo-svgr/.

Aditya Challa·5 October 2026·4 min read

Hands-on
On this page
  1. What I tested
  2. How much did SVGO shrink the set?
  3. When is SVGR the right default?
  4. Should you switch SVG tooling?
  5. Sources
  6. Related

I ran 20 verbose SVG icons on this box: SVGO 4.1 median 34 ms and cut the set from 18,990 B to 12,410 B (~35% smaller). SVGR 8.1 turned the same files into React JSX in a median 35 ms (17,620 B of components).

Short answer: use SVGO when you ship static .svg assets. Use SVGR when the icons must be React components. Add @svgr/plugin-svgo when you want both (63 ms median here). No affiliate links in this post.

What I tested

  • Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 00:22–00:23 IST.
  • Versions: svgo 4.1.0; @svgr/core 8.1.0 with @svgr/plugin-jsx and @svgr/plugin-svgo; Node 22.20.0.
  • Fixture: /workspace/bench-svgo-svgr/icons/. Twenty hand-made 128×128 SVGs with XML prolog, comments, unused xmlns:xlink, empty defs, and verbose attributes (18,990 B total).
  • Runs: (1) svgo optimize multipass write .svg; (2) @svgr/core + plugin-jsx only; (3) @svgr/core + plugin-svgo + plugin-jsx. Timing via performance.now around each full 20-file pass. 1 warm-up + 7 interleaved rounds.
  • Findings: SVGO median 34 ms (min 30 / max 43), out 12,410 B. SVGR-only median 35 ms (33–40), out 17,620 B JSX. SVGR+SVGO median 63 ms (56–75), out 12,920 B JSX.
  • One surprise: SVGR alone was almost as fast as SVGO on this small set, but the JSX stayed larger than the optimized SVG until the SVGO plugin ran.
  • Not tested: @svgr/cli webpack/vite loaders, TypeScript output, native SVG sprites, React Native, animated SVG, SVGO browser build, Windows or macOS.

How much did SVGO shrink the set?

PathMedian wallMin / MaxOutput bytes
SVGO 4.1 multipass (.svg)34 ms30 / 4312,410 B
SVGR 8.1 JSX only35 ms33 / 4017,620 B
SVGR + plugin-svgo63 ms56 / 7512,920 B

Source total was 18,990 B across 20 files. SVGO removed about 35% of the bytes and kept .svg on disk. SVGR trades file size for importable components. For asset-weight budgets after icons land in a bundle, see size-limit vs bundlesize and source-map-explorer vs webpack-bundle-analyzer.

When is SVGR the right default?

Pick SVGR when icons need props, theming, or tree-shaken imports inside React. The plain JSX path here finished in 35 ms median — fine for a 20-icon set. Turn on @svgr/plugin-svgo if you care about the JSX byte count; that path cost 63 ms and landed near the SVGO-optimized size.

Stay on SVGO alone for static public/ icons, email HTML, or any pipeline that never imports SVG as a component. Pairing SVGO with a CSS toolchain decision is closer to Lightning CSS vs PostCSS than to a React transform.

Should you switch SVG tooling?

SituationMy pick
Static .svg in public/ or CMS uploadsSVGO
React icon components with propsSVGR (+ plugin-svgo)
Both static assets and React importsSVGO for assets; SVGR for components
Huge icon monorepos in CIMeasure; this lab was only 20 files
Raster thumbnails, not vectorsSee Sharp vs Jimp instead
Vite app watching total asset weightPair with Vite vs Parcel​

Bottom line: on 20 verbose icons, SVGO returned in 34 ms median and cut ~35% of the bytes; SVGR made JSX in 35 ms; SVGR+SVGO needed 63 ms. Who should not switch: teams already happy with an SVG sprite sheet and no React icon imports.

How this was made: I generated 20 noisy SVG fixtures on the ShopperCove box, installed svgo and @svgr/core with the JSX and SVGO plugins, timed interleaved 20-file passes after a warm-up, recorded JSON medians and output bytes; the write-up was drafted with AI help and checked against that output.

Sources

  • https://svgo.dev/
  • https://github.com/svg/svgo
  • https://react-svgr.com/
  • https://www.npmjs.com/package/svgo
  • https://www.npmjs.com/package/@svgr/core

Related

  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/sharp-vs-jimp
  • https://www.shoppercove.com/blog/lightningcss-vs-postcss
  • https://www.shoppercove.com/blog/vite-vs-parcel
  • https://www.shoppercove.com/blog/source-map-explorer-vs-webpack-bundle-analyzer
  • https://www.shoppercove.com/blog/unocss-vs-tailwind
  • https://www.shoppercove.com/blog/dprint-vs-prettier
  • https://www.shoppercove.com/blog/oxlint-vs-eslint
svgosvgrsvgreactjsxbenchmarkingoptimizationweb performance

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~00:22–00:23 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). svgo 4.1.0 vs @svgr/core 8.1.0 (+ @svgr/plugin-jsx, @svgr/plugin-svgo). Fixture /workspace/bench-svgo-svgr/: 20 verbose 128×128 SVGs, 18,990 B total; (1) SVGO multipass, (2) SVGR JSX only, (3) SVGR+plugin-svgo. 1 warm-up + 7 interleaved rounds. Medians SVGO 34 ms (30–43) / 12,410 B; SVGR 35 ms (33–40) / 17,620 B; SVGR+SVGO 63 ms (56–75) / 12,920 B. Raw: /workspace/bench-svgo-svgr/res-svgo-svgr.json. Not tested: loaders, TS output, sprites, React Native, animated SVG, Windows/macOS. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 32

    Should You Leave PostCSS? 3ms vs 106ms

    Lightning CSS 1.33.0 vs PostCSS 8.5.29 + Autoprefixer 10.6.1 + cssnano 6.1.2 on a 76,864-byte CSS fixture: medians 3.16 ms vs 105.75 ms (~33x). Outputs 70498 vs 68474 B. Leave Autoprefixer+cssnano-only stacks for Lightning; keep PostCSS for plugins Lightning does not replace.

    5 Oct 2026

  • Plate 69

    oxlint vs ESLint: Should You Switch? 9.8s vs 0.09s

    oxlint 1.87.0 vs ESLint 9.39.4 on react-hook-form (301 files): 0.09 s vs 9.81 s single-thread (6.02 s with --concurrency auto, 1.10 s warm --cache). @oxlint/migrate ported 42 of 84 rules natively, 80 with JS plugins. 315 vs 562 warnings; seeded test 11/15 native, 13/15 with JS plugins, ESLint 15/15.

    5 Oct 2026

  • Plate 93

    UnoCSS vs Tailwind: 10.5KB vs 18.5KB CSS

    UnoCSS 66.5.2 (presetWind3) vs Tailwind CSS 4.1.13 (@tailwindcss/vite) on Vite 7.3.6: 80 HTML cards, same utility set, minify off. CSS 10,454 B (118 selectors) vs 18,473 B (119). Warm vite build medians (7 rounds, cache cleared): Uno 749 ms vs Tailwind 416 ms. Fixture /workspace/bench-unocss-tw/.

    5 Oct 2026

On this page

  1. What I tested
  2. How much did SVGO shrink the set?
  3. When is SVGR the right default?
  4. Should you switch SVG tooling?
  5. Sources
  6. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove