@jiihpeeh/svgoo-wasm
v4.1.5
Published
Typed TypeScript bindings for svgoo — the Rust port of SVGO — compiled to WebAssembly (glue-free C ABI, zero JS imports).
Maintainers
Readme
@jiihpeeh/svgoo-wasm
TypeScript bindings for svgoo — the port of SVGO to Rust — compiled to
WebAssembly over a glue-free C ABI with zero JavaScript imports. The same
module runs in browsers, Node.js and workers, and can offload every
optimize() call to a dedicated thread.
Highlights
- SVGO, compiled. The full SVGO 4.x plugin pipeline, ported to Rust and
shipped as a single small
.wasmmodule — no Node, no browser APIs involved. - Environment-agnostic core. One loader-free engine; the
browser/nodeentries (chosen via packageexportsconditions) install nothing but afetch- orfs-based wasm loader. - Worker mode.
optimize(svg, { worker: true })runs on a dedicated worker so the calling thread stays responsive. Everything inside the worker is imported lazily, so the main bundle stays small. - Tree-shakeable. The barrel re-exports small, side-effect-light units
(
core,plugin,errors); bundlers drop the parts you never import. - Type-safe plugins. Plugin names are a typed enum (
PluginName), read from the running engine itself so constants can't drift from the wasm.
Install
npm install @jiihpeeh/svgoo-wasm
# pnpm add @jiihpeeh/svgoo-wasm
# yarn add @jiihpeeh/svgoo-wasm
# bun add @jiihpeeh/svgoo-wasmCDN (jsDelivr)
The package is served by jsDelivr straight from npm. Pin a version for the browser cache to hit:
// ESM module bundle (esbuild/Rollup build of the browser entry)
// https://cdn.jsdelivr.net/npm/@jiihpeeh/[email protected]/+esm
// raw assets, served directly (content-addressed, immutable):
// https://cdn.jsdelivr.net/npm/@jiihpeeh/[email protected]/dist/browser.js
// https://cdn.jsdelivr.net/npm/@jiihpeeh/[email protected]/dist/svg_wasm_4.1.0_fix_04.wasmBecause the +esm bundle loads the wasm through a lazy core.js sub-bundle (a
separate module instance, so setWasmLoader/setDefaultUrl do not reach the
auto-load path), fetch the pinned wasm and load() it explicitly:
<script type="module">
import { optimize, fetchWasmBytes, load } from "https://cdn.jsdelivr.net/npm/@jiihpeeh/[email protected]/+esm";
const wasm = "https://cdn.jsdelivr.net/npm/@jiihpeeh/[email protected]/dist/svg_wasm_4.1.0_fix_04.wasm";
await load(await fetchWasmBytes(wasm));
const { data } = await optimize("<svg xmlns='x'><!-- hello --></svg>");
console.log(data);
</script>worker: true from a CDN pull needs a same-origin Worker, so copy
dist/worker.js (and the wasm) to your host before enabling it.
Quick start — Node.js
import { optimize } from "@jiihpeeh/svgoo-wasm";
const { data } = await optimize("<svg xmlns='x'><!-- hello --></svg>");The compiled engine (svg_wasm_4.1.0_fix_04.wasm) ships inside the package; the Node entry
reads it off disk automatically.
Quick start — browser (bundlers)
import { optimize, PluginName, only } from "@jiihpeeh/svgoo-wasm";
const { data } = await optimize("<svg xmlns='x'><path d='M0 0 10 10' /></svg>", {
plugins: only(PluginName.RemoveEmptyText), // just this one plugin
});Bundlers honoring exports conditions pick the browser entry, and the engine
is delivered by default: the browser entry points at the package's own
.wasm via a static new URL(..., import.meta.url) asset, which Vite and
webpack 5 emit into your app automatically — nothing extra to serve. For CDN
<script type="module"> and esbuild-style setups, place dist/svg_wasm_4.1.0_fix_04.wasm
next to your bundle; to load from elsewhere:
import { setDefaultUrl } from "@jiihpeeh/svgoo-wasm";
setDefaultUrl("/wasm/svg_wasm_4.1.0_fix_04.wasm");Worker mode
const { data } = await optimize(markup, { worker: true });The bindings spawn their own module worker (dist/worker.js) via
new URL(..., import.meta.url), batch the config, and optimize there. In
Node.js this is backed by node:worker_threads; in browsers by a Worker.
If no Worker is available — or it fails — the call falls back to the main
thread and still succeeds.
Bundler note: Vite and webpack resolve the worker asset automatically. esbuild
and CDN <script type="module"> users should serve dist/worker.js and
dist/svg_wasm_4.1.0_fix_04.wasm alongside their bundle.
API
| Export | Description |
| --- | --- |
| optimize(svg, config?) | Asynchronously optimize an SVG string; auto-loads the engine (worker mode opt-in via config.worker). |
| optimizeSync(svg, config?) | Synchronous variant; requires a prior load(). |
| plugins() / pluginsSync() | Runtime-resolved plugin names in SVGO order (preset-default first). |
| load(bytes) / loadUrl(url) / setDefaultUrl(url) | Load / locate the wasm engine. |
| setWasmLoader(fn) | Install a custom bytes loader for embedded engines. |
| isLoaded() / reset() | Query load state / eject the engine. |
| SvgoError / classifyError() | Typed errors (kind, plugin, message) for config and engine failures. |
| shutdownWorkers() | Terminate idle workers explicitly. |
| PluginName, ALL, isPluginName() | Plugin enum, registry list, and guard. |
| plugin(name, params?), only(...), drop(...), preset() | Builders for config.plugins. |
| VERSION | Package version, synced with the crate. |
Lower-level primitives (acquire, consumeResult, instantiateWasmEngine,
normalizeConfig, EngineSession, WasmLoader, WasmExports) are exported
for embedding / exotic loaders.
config mirrors SVGO's own optimize(svg, config): plugins accepts plain
names, raw SVGO spellings and { name, params } entries; an omitted config
selects the default preset-default plugin set.
Building the wasm from source
For developers who want to rebuild the .wasm (only git, cargo with the
wasm32-unknown-unknown target, and Node are needed):
npm run build:wasmscripts/wasm-build.mjs uses a sibling ../rs checkout when present (the
demo layout), otherwise it clones the Rust source from git
(SVGOO_REPO, default https://gitlab.com/jiiihpeeh/svgoo.git) into
.cache/svgoo and updates it with git pull. Point SVGOO_SRC at a
checkout to pin an exact source tree.
The full package gate (wasm build, typecheck, Node-free-dist check, smoke suite, example) runs with:
npm testLicense
MIT. svgoo is a translation of SVGO (MIT, © Kir Belevich).
