Takumi

Comparison

Compare takumi-pdf, react-pdf, and Puppeteer using recorded invoice benchmarks and rendering tradeoffs.

This page records one benchmark, an 80-line invoice rendered by three PDF renderers. The numbers hold for the package versions and machine listed here, not for current releases.

  • Each harness uses its renderer's own template language.
  • Geometry, columns, and the embedded font (Inter 400/700) match across harnesses. react-pdf's pt values mirror the other renderers' px values.
  • takumi and Chrome produce the same two-page layout.
  • Warm figures are the median of 20 renders.

The environment is Apple M1 Pro, macOS 15.7.4, Bun 1.3.14, and Chrome 151.

The bench source now depends on newer package versions. Run bun bench there to measure them on your machine.

takumi-pdf 0.4@react-pdf/renderer 4.5.1Puppeteer + Chrome
Cold start to first PDF176 ms495 ms0.7–2.8 s
Warm render (median)26 ms236 ms198 ms
Output size19 KB (15 KB with tagged: false)16 KB52 KB
Deploy needs1.5 MB gzip wasmpure JSChrome install (hundreds of MB)
Template languageJSX, HTML, node trees with CSS and Tailwindits own primitives (<View>, <Text>, StyleSheet)HTML with full CSS
Selectable text, subset fontsyesyesyes
Arabic and bidi textyesshaping only, manual directionyes
Runs on edge runtimesyes (Cloudflare Workers)no (Node)no

Bundle and install size

These figures come from npm-registry packages bundled with esbuild (--bundle --minify, then gzip). Install size comes from a clean bun add.

JS bundle (min+gzip)wasm (gzip)node_modules
takumi-pdf 0.410 KB1.52 MB (1.16 MB brotli)4.2 MB, 45 files
@react-pdf/renderer 4.5.1493 KB—32 MB, 1998 files
pdf-lib 1.17.1179 KB—26 MB
pdfkit 0.19.1253 KB—23 MB
jspdf 4.2.1248 KB—59 MB
Puppeteer + Chrome——Chrome install (hundreds of MB)

pdf-lib, pdfkit, and jspdf are drawing libraries, so you position each text line yourself. They are not in the benchmark above.

These figures exclude application code. Measure the complete bundle for your own deployment target.

Interpret the results

Puppeteer

  • Cold start includes launching a browser process, and it varies with machine state.
  • Chrome's memory spans several processes, which a single-process measurement misses.
  • Chrome is fast once warm, and its CSS support is the most complete of the three.

react-pdf

  • It embeds the same Inter subsets as the other two. Subsetting on every render is most of its warm cost. The 14 standard PDF fonts avoid that cost.
  • Documents use react-pdf's own components, so existing HTML, JSX, and Tailwind markup cannot be reused.
  • It shapes Arabic, but paragraph direction is manual. In this benchmark, the Arabic sample lost its first letter.

takumi-pdf

  • It renders the same components as takumi's image output, unchanged.
  • Its CSS coverage is narrower than Chromium's. PDF output rejects filter: blur() and drop-shadow(), and does not draw backdrop-filter.
  • Blurred box-shadow and text-shadow are approximated with stepped bands.
  • Tagged output is on by default and added about 4 KB to this invoice. tagged: false removes it.

Choose a renderer

  • Puppeteer uses browser layout and runs page scripts.
  • react-pdf uses its own document components.
  • takumi-pdf takes HTML, JSX, and node trees with its supported CSS.

Run your own documents through the benchmark before you use these timings to plan capacity.

Last updated on