svgo
A Node.js library and command-line tool that optimizes SVG files by removing redundant markup through a configurable plugin pipeline.
Repository Health
Technical Analysis
SVGO (SVG Optimizer) strips the bloat that vector editors like Illustrator, Sketch, and Figma leave behind in exported SVG files — editor metadata, comments, hidden elements, redundant IDs, default attribute values, and other markup that has no effect on rendering. It ships both as a global CLI (svgo file.svg -o file.min.svg) and as an importable optimize() function for build pipelines, bundler plugins, and asset-processing scripts.
Under the hood it parses SVG into an internal AST via a SAX-based parser, runs a configurable chain of 30+ built-in plugins over that tree (each targeting one specific class of redundancy — collapsing groups, merging paths, converting shapes to path data, cleaning numeric precision), then re-serializes the optimized tree back to a string. The default plugin set (preset-default) can be selectively overridden, extended with custom plugins, or replaced outright via svgo.config.mjs.
SVGO is a foundational piece of the front-end asset pipeline for a large share of the JavaScript ecosystem: it’s the optimizer underneath most SVG-handling Webpack/Vite/Rollup loaders, icon-sprite generators, and static-site build tools. Its multipass mode reruns the plugin chain until output size stops shrinking, squeezing out savings later passes alone would miss.
What You Get
- A global CLI (
svgo) for optimizing single files or entire directories recursively - An importable
optimize()function for embedding SVG optimization directly in Node.js code or bundler plugins - 30+ built-in plugins covering redundant metadata removal, path/shape merging, numeric cleanup, color conversion, and ID minification
- A
preset-defaultplugin bundle that can be selectively overridden per-plugin viasvgo.config.mjs - Support for fully custom plugins defined inline or imported from other files
- A
loadConfig()helper so downstream tools built on SVGO can resolve the same config-file convention
Common Use Cases
- Optimizing exported SVG icons and illustrations before shipping them to production
- Running as part of a Webpack, Vite, or Rollup asset pipeline to auto-minify imported SVGs
- Batch-processing an entire directory of design-tool exports via the recursive CLI flags
- Stripping editor cruft (Illustrator/Sketch/Figma metadata) from SVGs before committing them to a repo
- Generating compact base64/URL-encoded data URIs from SVG source for inline embedding
Under The Hood
Architecture
SVGO runs a strict three-stage pipeline: parser.js uses a SAX-based streaming parser (the sax dependency) to turn raw SVG text into an internal AST defined in xast.js, svgo.js’s optimize() function then walks that tree through invokePlugins() running each configured plugin from plugins/ in sequence, and stringifier.js serializes the transformed tree back to a string. Each plugin (in plugins/*.js, e.g. collapseGroups.js, convertPathData.js, cleanupIds.js) is a self-contained visitor targeting one narrow transformation, registered through createPreset() in plugins/preset-default.js so the default plugin set is just a curated list rather than special-cased logic. The svgo-node.js entry point wraps the platform-agnostic core (svgo.js) with Node-specific concerns — config-file resolution via loadConfig() and OS-appropriate line endings — while bin/svgo.js layers a Commander-based CLI (lib/svgo/coa.js) on top of that same core, so CLI, Node API, and browser bundle all share one optimization engine with no logic duplicated between entry points.
Tech Stack
The core has a deliberately small runtime dependency footprint: sax for XML parsing, css-tree/css-select/css-what for parsing and matching CSS selectors used by style-related plugins (inlineStyles.js, minifyStyles.js), csso for CSS minification, commander for CLI argument parsing, and picocolors for terminal output. The project is authored as native ESM (type: module) with a separate dist/ CJS/browser build produced by Rollup, and ships hand-written TypeScript declaration files built via tsc against tsconfig.build.json rather than being authored in TypeScript directly — most of lib/ and plugins/ remain plain JavaScript with JSDoc type annotations checked under strict mode. Testing runs on Vitest, with a separate test:regression pipeline that renders before/after SVGs with Playwright and diffs them pixel-by-pixel via pixelmatch to catch visual regressions the unit tests wouldn’t.
Code Quality
The repo has substantial test coverage — 18+ *.test.js files sit alongside their corresponding implementation files (parser.test.js, path.test.js, style.test.js, xast.test.js), plus a large fixture-driven plugin test suite and the separate pixel-diff regression suite for visual correctness, which is an unusually rigorous check for a text-transformation tool. ESLint (flat config, eslint.config.mjs) with eslint:recommended plus JSDoc/type-checking via tsc --strict on JS files (checkJs: true) stands in for a full TypeScript rewrite while still catching type errors; Prettier formats consistently, and CI (ci.yml, codeql.yml, regression.yml) runs lint, typecheck, unit tests, bundle tests, and the regression suite on every change. Error handling favors explicit thrown Errors with descriptive messages (e.g. unknown plugin names, malformed config) over silent fallbacks.
API Design
The public API surface is intentionally minimal: a single optimize(svgString, config) function returning { data }, plus loadConfig() for config-file resolution — there’s no class hierarchy or builder pattern to learn. Configuration is a plain object matching the same shape whether it’s passed inline or loaded from svgo.config.mjs, and the plugin config format ('name' string, or { name, params } for built-ins, or { name, params, fn } for fully custom logic) scales smoothly from zero-config default use up to hand-written custom transforms without a second API to learn. This low-ceremony design is a large part of why SVGO is embedded inside so many other tools’ build pipelines rather than only used standalone.
Used by 23 apps in this directory
SearXNG
Search
Privacy-first metasearch engine that aggregates results from 250+ search services — no tracking, no profiling, full control when self-hosted.
SigNoz
Analytics · Monitoring
Self-host your entire observability stack — logs, metrics, traces, and LLM monitoring — in one OpenTelemetry-native platform, without the Datadog bill.
Teleport
Authentication · Security
Zero-trust infrastructure access platform that replaces credentials and VPNs with short-lived certificates, SSO, and identity-aware proxies for SSH, Kubernetes, databases, RDP, and AI agents.
Webstudio
Design Tools · No Code Platforms
Open source visual development platform with complete CSS control, headless CMS integration, and full infrastructure ownership
Zulip
Team Chat
Topic-based team chat that brings the structure of email threads to real-time messaging, so distributed teams never lose context across hundreds of concurrent conversations.