babel-plugin-inline-react-svg
A Babel plugin that transforms SVG file imports into optimized, inlined React components at build time.
Repository Health
Technical Analysis
babel-plugin-inline-react-svg rewrites import Icon from './icon.svg' (or the equivalent require) into an inline functional React component at compile time, so consumers never ship a raw file reference or an extra network request for each icon. Before inlining, it runs the SVG markup through SVGO to strip bloat like comments, doctypes, and redundant attributes, then converts the result into JSX-safe syntax — kebab-case and namespaced attributes become camelCase, class becomes className, inline style strings become style objects, and a {...props} spread is added to the root <svg> element automatically.
Because it operates purely as a Babel visitor with no runtime dependency shipped to the browser, teams can drop it into an existing .babelrc and immediately treat every SVG import as a first-class, prop-driven React component without hand-authoring wrapper components or maintaining a separate icon-component build step.
What You Get
- Automatic conversion of SVG file imports/requires into inline React functional components
- Built-in SVGO optimization of the SVG markup, with a
svgooption to customize or disable it - JSX-safe attribute conversion: kebab-case and namespaced attributes to camelCase,
classtoclassName,stylestrings to style objects - Automatic
propsspreading onto the root<svg>element and hoisting of static attributes intodefaultProps - Support for default imports/requires, named re-exports (
export { default as X }), and export-all syntax - Optional
ignorePatternandcaseSensitiveoptions for selective and cross-platform-safe file matching
Common Use Cases
- Converting a directory of icon SVGs into React components without hand-writing wrapper components for each one
- Build pipelines that consume raw SVG exports from design tools and need them turned into importable components automatically
- Reducing bundle/network overhead by inlining small SVGs directly into component output instead of loading them as separate assets
- Enforcing case-sensitive SVG file paths in CI so imports that work on macOS/Windows don’t break on case-sensitive Linux production filesystems
Under The Hood
Architecture
The plugin is a single Babel visitor (src/index.js) built with @babel/helper-plugin-utils’s declare, watching Program, CallExpression (for require), ImportDeclaration, and ExportNamedDeclaration nodes for SVG-file references. On a match it resolves the file path with resolve/sync (honoring symlinks and an optional case-sensitivity check via fileExistsWithCaseSync.js), reads the raw SVG, optionally runs it through optimize.js (a thin, validating wrapper around SVGO), escapes curly braces for JSX safety (escapeBraces.js), re-parses the sanitized markup with @babel/parser, and rewrites its JSX attributes with a dedicated visitor (transformSvg.js, backed by camelize.js and cssToObj.js for attribute/style normalization). A Babel template then builds the replacement functional-component AST, hoisting non-spread attributes into a defaultProps object and injecting a React import only if one isn’t already in scope. Each helper module is small, pure, and narrowly scoped, so the design holds up well as long as callers don’t change the assumed shape of the visitor/template contract.
Tech Stack
Built as a Babel 7 plugin (peer dependency @babel/core ^7.0.0), using @babel/parser for a second JSX-aware parse pass and @babel/helper-plugin-utils for the plugin declaration boilerplate. SVGO ^2.8.0 handles markup optimization, resolve ^2.0.0-next.5 handles Node-style module resolution, and lodash.isplainobject guards a type check in the SVGO-options validator. Dev tooling includes @babel/cli/@babel/node for building and running tests, ESLint with eslint-config-airbnb, auto-changelog for release notes, and aud for a post-test dependency-vulnerability audit; the published package ships a lib/ build compiled from src/.
Code Quality
Tests live in test/sanity.js, a single hand-rolled script (not a framework like Jest or Mocha) that transforms a set of JSX fixtures under test/fixtures/ via @babel/core’s transformFile and asserts correctness with manual regex checks and thrown errors rather than an assertion library; there’s no coverage reporting. Error handling is explicit but coarse — the plugin throws plain Error/TypeError for misuse (missing filename option, unresolvable SVG path, case mismatch) instead of typed error classes. The codebase is untyped JavaScript with no shipped type declarations, though ESLint (airbnb config) runs as a pretest step and CI executes on every push/PR via GitHub Actions.
API Design
The plugin is zero-config for the common case — adding "inline-react-svg" to a .babelrc plugins list is enough, since import Icon from './icon.svg' just becomes <Icon /> with no new import syntax to learn. Power users get three well-documented options (ignorePattern, caseSensitive, svgo) with sensible defaults and an explicit escape hatch (svgo: false) to skip optimization entirely, and non-spread SVG attributes are automatically lifted into defaultProps so consumers can still override them like normal React props. Documentation is a single concise README covering .babelrc, CLI, and Node-API usage, though no TypeScript types are published, so consumers on TS get no autocompletion or type-checking on the transformed import.