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 22 apps in this directory
APITable
Low Code Platforms · Databases
API-first collaborative spreadsheet-database platform that auto-generates REST APIs and lets teams build internal tools, CRMs, and dashboards without code.
Appsmith
Developer Tools · Automation · No Code Platforms
Open-source low-code platform to build admin panels, dashboards, and internal tools connected to any database or API.
Cherry Studio
AI Assistants
All-in-one AI desktop client with 300+ assistants and multi-model support
CodeSandbox
Code Editors · Developer Tools
Instantly ready browser-based IDE that runs full npm dependency resolution and transpilation entirely client-side, with no server needed.
Colanode
Knowledge Management · Team Chat · Collaboration
Local-first, self-hosted workspace that combines real-time chat, Notion-style pages, and structured databases — all synced via CRDTs so you work offline without losing a keystroke.
Cozy Stack
File Storage · Productivity
Self-hosted personal cloud platform that unifies your files, apps, and devices in one private space you fully control.
Forem
Community · Blogging
Open source Ruby on Rails platform for building developer communities with articles, discussions, and social profiles—the same software that powers dev.to.
GitButler
Developer Tools · Devops · AI Development
Git, but better — a modern version control client with stacked branches, parallel workflows, unlimited undo, and first-class support for AI-powered development.
Gitea
Devops · Developer Tools · Project Management
Self-hosted DevOps in a single Go binary — Git hosting, GitHub Actions-compatible CI/CD, and 30+ package registries without any SaaS dependency.