resvg-js is a high-performance SVG renderer and toolkit, powered by Rust based resvg, with Node.js backend using napi-rs, also a pure WebAssembly backend.
Please use all lowercase resvg-js when referencing project names.
Playground
Features
- Fast, safe and zero dependencies, with correct output.
- Convert SVG to PNG, includes cropping, scaling and setting the background color.
- Support system fonts and custom fonts in SVG text.
v2: Gets the width and height of the SVG and the generated PNG.v2: Support for outputting simplified SVG strings, such as converting shapes(rect, circle, etc) to<path>.v2: Support WebAssembly.v2: Support to get SVG bounding box and crop according to bounding box.v2: Support for loading images of external links in<image>.- No need for node-gyp and postinstall, the
.nodefile has been compiled for you. - Cross-platform support, including Apple M Chips.
- Support for running as native addons in Deno.
Installation
Node.js
npm i @resvg/resvg-js
Browser(Wasm)
<script src="https://unpkg.com/@resvg/resvg-wasm"></script>
Docs
- Node.js see index.d.ts
- Wasm see wasm/index.d.ts
Example
Node.js Example
This example will load Source Han Serif, and then render the SVG to PNG.
node example/index.js Loaded 1 font faces in 0ms. Font './example/SourceHanSerifCN-Light-subset.ttf':0 found in 0.006ms. ✨ Done in 55.65491008758545 ms
Deno Example
deno run --unstable --allow-read --allow-write --allow-ffi example/index-deno.js [2022-11-16T15:03:29Z DEBUG resvg_js::fonts] Loaded 1 font faces in 0.067ms. [2022-11-16T15:03:29Z DEBUG resvg_js::fonts] Font './example/SourceHanSerifCN-Light-subset.ttf':0 found in 0.001ms. Original SVG Size: 1324 x 687 Output PNG Size : 1200 x 623 ✨ Done in 66 ms
| SVG | PNG |
|---|---|
![]() |
Usage
Node.js
const { promises } = require('fs') const { join } = require('path') const { Resvg } = require('@resvg/resvg-js') async function main() { const svg = await promises.readFile(join(__dirname, './text.svg')) const opts = { background: 'rgba(238, 235, 230, .9)', fitTo: { mode: 'width', value: 1200, }, font: { fontFiles: ['./example/SourceHanSerifCN-Light-subset.ttf'], // Load custom fonts. loadSystemFonts: false, // It will be faster to disable loading system fonts. // defaultFontFamily: 'Source Han Serif CN Light', // You can omit this. }, } const resvg = new Resvg(svg, opts) const pngData = resvg.render() const pngBuffer = pngData.asPng() console.info('Original SVG Size:', `${resvg.width} x ${resvg.height}`) console.info('Output PNG Size :', `${pngData.width} x ${pngData.height}`) await promises.writeFile(join(__dirname, './text-out.png'), pngBuffer) } main()
Bun
Starting with Bun 0.8.1, resvg-js can be run directly in Bun without any modification to the JS files, and is fully compatible with the syntax in Node.js.
bun example/index.js
Deno
Starting with Deno 1.26.1, there is support for running Native Addons directly from Node.js. This allows for performance that is close to that found in Node.js.
deno run --unstable --allow-read --allow-write --allow-ffi example/index-deno.js
import * as path from 'https://deno.land/std@0.159.0/path/mod.ts' import { Resvg } from 'npm:@resvg/resvg-js' const __dirname = path.dirname(path.fromFileUrl(import.meta.url)) const svg = await Deno.readFile(path.join(__dirname, './text.svg')) const opts = { fitTo: { mode: 'width', value: 1200, }, } const t = performance.now() const resvg = new Resvg(svg, opts) const pngData = resvg.render() const pngBuffer = pngData.asPng() console.info('Original SVG Size:', `${resvg.width} x ${resvg.height}`) console.info('Output PNG Size :', `${pngData.width} x ${pngData.height}`) console.info('✨ Done in', performance.now() - t, 'ms') await Deno.writeFile(path.join(__dirname, './text-out-deno.png'), pngBuffer)
WebAssembly
This package also ships a pure WebAssembly artifact built with wasm-bindgen to run in browsers.
Browser
<script src="https://unpkg.com/@resvg/resvg-wasm"></script> <script> ;(async function () { // The Wasm must be initialized first await resvg.initWasm(fetch('https://unpkg.com/@resvg/resvg-wasm/index_bg.wasm')) const font = await fetch('./fonts/Pacifico-Regular.woff2') if (!font.ok) return const fontData = await font.arrayBuffer() const buffer = new Uint8Array(fontData) const opts = { fitTo: { mode: 'width', // If you need to change the size value: 800, }, font: { fontBuffers: [buffer], // New in 2.5.0, loading custom fonts }, } const svg = '<svg> ... </svg>' // Input SVG, String or Uint8Array const resvgJS = new resvg.Resvg(svg, opts) const pngData = resvgJS.render(svg, opts) // Output PNG data, Uint8Array const pngBuffer = pngData.asPng() const svgURL = URL.createObjectURL(new Blob([pngData], { type: 'image/png' })) document.getElementById('output').src = svgURL })() </script>
See playground, it is also possible to call Wasm in Node.js, but it is slower.
Sample Benchmark
npm i benny@3.x sharp@0.x @types/sharp svg2img@0.x npm run bench
Running "resize width" suite...
resvg-js(Rust):
12 ops/s
sharp:
9 ops/s
skr-canvas(Rust):
7 ops/s
svg2img(canvg and node-canvas):
6 ops/sSupport matrix
Test or Contributing
-
Install latest
Rust -
Install
Node.js@10+which fully supportedNode-API -
Install
wasm-packcurl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | shNormally
wasm-packwill installwasm-bindgenautomatically, but if the installation fails due to network reasons, please try to install it manually.cargo install wasm-bindgen-cli
On computers with Apple M chips, the following error message may appear:
Error: failed to download from https://github.com/WebAssembly/binaryen/releases/download/version_90/binaryen-version_90-x86_64-apple-darwin.tar.gz
Please install binaryen manually:
brew install binaryen
Build Node.js bindings
npm i
npm run build
npm testBuild WebAssembly bindings
npm i npm run build:wasm npm run test:wasm
Upgrade Yarn
This project uses Yarn v4. To upgrade to a newer version, run:
yarn set version stableThis will automatically download the latest stable Yarn from repo.yarnpkg.com and update the yarnPath in .yarnrc.yml.
Note: If the yarn executable fails to start due to a missing binary, temporarily modify
yarnPathin.yarnrc.ymlto your current version to bootstrap, then run the upgrade command.
Roadmap
I will consider implementing the following features, if you happen to be interested, please feel free to discuss with me or submit a PR.
- Support async API
- Upgrade to napi-rs v2
- Support WebAssembly
- Output usvg-simplified SVG string
- Support for getting SVG Bounding box
- Support for generating more lossless bitmap formats, e.g. avif, webp, JPEG XL
Release package
We use GitHub actions to automatically publish npm packages.
# 1.0.0 => 1.0.1 npm version patch # or 1.0.0 => 1.1.0 npm version minor
License
Please use all lowercase resvg-js when referencing project names.
Copyright (c) 2021-present, yisibl(一丝)
