The SVG workflow that keeps your React bundle small
How to take a Figma export from 15KB to 400 bytes, convert it into a clean React component, and ship icons without a bloated icon library.
Why raw Figma / Illustrator SVGs are enormous
A 24ร24 icon exported from Figma is often 3-8 KB. The actual visual content - a couple of <path> elements - is 200-400 bytes. The rest is:
- Editor metadata (
sodipodi:namedview,inkscape:...attributes,sketch:typeattributes). <title>and<desc>blocks with the layer name.<metadata>block with the app version.- Path coordinates written to 8-10 decimal places (
M12.00000000 2.00000000). - Empty
<g>groups from the export step. xmlns:*declarations for namespaces nothing uses.- Redundant
fill-opacity="1",stroke-opacity="1"attributes.
Ship those raw and every icon in your project pays the tax.
The passes that actually matter
Optimization passes ranked by size impact on typical Figma exports:
- Round path decimals.
M12.00000000 2.00000000โM12 2. Biggest single win - often 40-50% of the file. - Strip metadata + editor namespaces. 15-25% more.
- Remove empty groups. 5-10%.
- Collapse whitespace. 5-10%.
- Remove default attributes. Small but free.
Together: a typical 5KB Figma icon becomes 400-800 bytes with zero visual change.
SVG Optimizer runs all six passes with toggles and shows before/after size. Everything runs in-browser via string manipulation - no server round-trip.
When to be careful with decimal precision
The default 2-decimal precision is safe for icons. Below 1 decimal, tight curves can visibly deform. If your SVG is a complex illustration (a logo mark with subtle curves, an infographic), keep precision at 2 or 3.
For UI icons (Lucide, Heroicons, Phosphor scale), 1-decimal precision is imperceptible and saves another 10-15%.
SVG in React: three approaches
1. <img src="/icon.svg" />. Simplest. External file, cached separately. Loses reactivity - you can't change the color from a prop, and the icon may flash on load.
2. Inline SVG as a React component. Full control - pass color as a prop, animate paths, apply CSS. This is what every serious icon library does.
3. SVG sprite (<use xlinkHref="#icon-foo" />). All icons in one file, referenced by ID. Good for very large icon sets; annoying to maintain by hand.
Most React projects should default to option 2. Costs a few bytes per icon; unlocks styling, animation, and no network request.
Converting SVG โ React component
The transforms:
classโclassName- Kebab-case attributes โ camelCase (
stroke-widthโstrokeWidth,fill-ruleโfillRule) style="color: red"โstyle={{ color: "red" }}- Root
<svg>forwards props so<Icon className="foo" onClick={...} />works - Optional
React.memowrap for pure components - Optional TypeScript typing (
React.SVGProps<SVGSVGElement>)
Doing this by hand for one icon is fast. Doing it for a hundred is where automation earns its keep.
SVG to JSX applies all transforms in one paste - pick a component name, choose TypeScript or JavaScript, choose whether to wrap in React.memo, and copy.
The two-step workflow for building an icon set
The pattern that produces the smallest React bundle:
- Design each icon at 24ร24 in Figma. Export as SVG.
- SVG Optimizer - every icon through the optimizer. Typical 5KB โ 500 bytes.
- SVG to JSX - convert each optimized SVG to a React component. Paste, copy, save to a file.
- Re-export them from an
icons/index.tsso consumers canimport { ChevronRight } from "@/icons".
Result: an icon set of 50-100 icons that costs 20-50KB total - smaller than a single icon library import.
When not to build your own icon set
Icon libraries earn their weight when:
- You need 500+ icons.
- The maintainer keeps them visually consistent (stroke width, corner radius, style).
- You use tree-shaking so only imported icons ship.
Lucide, Heroicons, Phosphor, Tabler, and Radix Icons all handle these well. Tree-shaking works if you import individually (import { ChevronRight } from "lucide-react"), not from a barrel.
The break-even point: if you need fewer than 20-30 icons, build your own. More than that, use a library.
Related tools
- SVG Optimizer - for the shrink step.
- SVG to JSX - for the React conversion.
- Image Converter - for the times you actually need PNG (email signatures, some external systems).
- Favicon Generator - SVG is now the preferred favicon format; run yours through the optimizer first.
Tools mentioned in this post
SVG Optimizer
Compress and clean SVG files - remove metadata, collapse groups, simplify paths
SVG โ JSX
Paste any SVG โ get a clean React component with prop-forwarding and camelCase attributes
Image Converter
Convert between PNG, JPG, and WebP in your browser - batch supported
Favicon Generator
Upload an image โ get every favicon size, apple-touch, PWA icons, ICO, and the HTML snippet
Related reading
Canva's AI image generator is the best thing to happen to solo game devs - here's the honest review
I finally sat down with Canva Dream Lab (the one built on Leonardo Phoenix) to make a game logo, and it changed my mind about AI art for indie devs. Here's what it's actually good at, where it falls apart, and the tiny stack of free tools that turns its output into ship-ready assets.
Favicon and app icon complete guide 2026 (every size, every platform)
The favicon.ico that still matters, the apple-touch-icon that isn't optional, the PWA icons that make you installable, and the iOS + Android sets your app needs on day one.
How to compress images without losing quality (JPG, PNG, WebP in 2026)
The math behind JPG quality, why WebP is now the smarter default, and the settings that give 60% file-size savings with no visible quality loss.
WebP vs JPG in 2026: why WebP won, and when JPG is still right
WebP files are 25-35% smaller than JPG at the same visual quality. Every browser supports it. Every CDN serves it. Here's why the JPG-vs-WebP debate is over - and the two edge cases where JPG still wins.
Shan builds 712 Tools. He holds a Master's degree in Mechanical Engineering and now works as a Software Engineer, shipping browser-based developer utilities out of Ontario, Canada. Learn more ยท 712studiogames@gmail.com