Plate 49
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 Challa4 min read
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?
| Path | Median wall | Min / Max | Output bytes |
|---|---|---|---|
| SVGO 4.1 multipass (.svg) | 34 ms | 30 / 43 | 12,410 B |
| SVGR 8.1 JSX only | 35 ms | 33 / 40 | 17,620 B |
| SVGR + plugin-svgo | 63 ms | 56 / 75 | 12,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?
| Situation | My pick |
|---|---|
| Static .svg in public/ or CMS uploads | SVGO |
| React icon components with props | SVGR (+ plugin-svgo) |
| Both static assets and React imports | SVGO for assets; SVGR for components |
| Huge icon monorepos in CI | Measure; this lab was only 20 files |
| Raster thumbnails, not vectors | See Sharp vs Jimp instead |
| Vite app watching total asset weight | Pair 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
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.
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