How Vite and Webpack Process and Bundle SVG Icons
Modern frontend build tools like Vite and Webpack provide multiple strategies for handling Scalable Vector Graphics (SVGs), ranging from treating them as static image assets to transforming them into reusable UI components. Depending on configuration and developer requirements, these bundlers process SVGs by emitting standalone files, inlining them as base64 or URL-encoded data strings, compiling them into framework-native components (such as React or Vue), or merging them into unified SVG sprite sheets. Understanding how these pipelines operate helps developers optimize network performance, reduce bundle sizes, and manipulate SVG attributes dynamically.
Static Asset Handling
By default, both Webpack and Vite treat SVGs imported in code as external static assets:
- Webpack: Modern Webpack (v5+) uses built-in Asset
Modules. Setting an import rule with
type: 'asset/resource'emits the SVG into the build output folder and replaces the import statement with the public URL string. - Vite: Powered by Rollup in production and native ES
modules in development, importing an SVG
(
import iconUrl from './icon.svg') resolves directly to its public serving path, appending a cache-busting content hash to the generated filename during production builds.
Inlining via Data URLs
To minimize separate HTTP requests for small icons, bundlers can inline SVGs directly into HTML, CSS, or JavaScript bundles as Base64 or UTF-8 encoded Data URIs:
- Webpack: Using
type: 'asset/inline'automatically converts the SVG content into a Data URI. Developers can also usetype: 'asset'with amaxSizerule to automatically switch between inlining small SVGs and emitting larger ones as standalone files. - Vite: Vite provides the
build.assetsInlineLimitconfiguration option (defaulting to 4 KB). Assets smaller than this threshold are automatically converted to Base64 data strings. Additionally, appending the?inlinequery suffix to an SVG import forces Vite to inline that specific file.
Component Transformation (SVG as Code)
A common pattern in modern web development is treating SVGs as
interactive components, allowing developers to pass props, manipulate
classes, and alter fill colors via CSS (currentColor).
- Webpack Pipelines: Webpack achieves this via
dedicated loaders such as
@svgr/webpackfor React orvue-svg-loaderfor Vue. The loader parses the raw XML string, passes it through an AST (Abstract Syntax Tree) compiler like Babel, and outputs a standard JavaScript/TypeScript component definition. - Vite Plugins: Vite handles component transformation
using plugins like
vite-plugin-svgrorvite-svg-loader. During the build lifecycle, the plugin intercepts the SVG import, executes the transformation, and returns an ES module containing the component code ready for framework consumption.
SVG Sprite Sheet Generation
For projects with extensive icon sets, bundling multiple SVGs into a
single sprite sheet using the <svg> and
<symbol> elements reduces DOM overhead and avoids
runtime component compilation costs.
Plugins like svg-sprite-loader (for Webpack) or
vite-plugin-svg-spritemap (for Vite) scan specified icon
directories, extract path and viewBox data, wrap each graphic in a
<symbol id="icon-name">, and compile them into a
single master SVG. In the application code, icons are rendered
efficiently using
<svg><use href="#icon-name" /></svg>.
Optimization with SVGO
Before SVGs are bundled, inlined, or converted to components, build tools typically run them through SVGO (SVG Optimizer). Integrated directly into loaders and plugins, SVGO strips XML doctypes, metadata, editor artifacts (from Figma or Illustrator), comments, and redundant geometric data, ensuring that only the minimal required path information is included in the production bundle.