Takumi

Comparison

Compare renderer behavior and recorded invoice benchmarks.

This page records a benchmark of an 80-line invoice across three PDF renderers. The numbers apply to the package versions and environment below, not necessarily the current releases.

Each harness uses its engine's native template language. Geometry, columns, and the embedded font (Inter 400/700) are the same in each harness. 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 bench source reproduces this table. Run it with bun bench.

Environment: Apple M1 Pro, macOS 15.7.4, Bun 1.3.14, Chrome 151.

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 measurements use npm-registry packages and esbuild (--bundle --minify, 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 KB32 MB, 1998 files
pdf-lib 1.17.1179 KB26 MB
pdfkit 0.19.1253 KB23 MB
jspdf 4.2.1248 KB59 MB
Puppeteer + ChromeChrome install (hundreds of MB)

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

Measure the complete bundle for your deployment target. These figures exclude application code and should not be used as a current platform size limit.

Interpret the results

  • Chrome's cold start includes launching a browser process. It varies with machine state. Its memory spans several processes. A single-process measurement misses this. Chrome performs well after warming. It has the most complete CSS support of the three.
  • react-pdf embeds the same Inter subsets as the other two. Subsetting on every render is most of its warm cost; the standard 14 PDF fonts avoid it. Documents use react-pdf's component set. Existing HTML, JSX, and Tailwind markup cannot be reused. It shapes Arabic, but paragraph direction is manual, and our Arabic sample dropped its first letter.
  • takumi-pdf reuses OG-image components unchanged. Its CSS coverage is narrower than Chromium's. PDF output does not support filter: blur(), drop-shadow(), or backdrop-filter. A blurred box-shadow is approximated with bands, and a blurred text-shadow draws sharp. Tagged output is on by default and adds about 4 KB to this invoice, down from 10 KB before the structure tree moved into an object stream. tagged: false removes it.

Choose based on your template and runtime. Puppeteer uses browser layout and executes page scripts. react-pdf uses document components. Takumi accepts HTML, JSX, and node trees with its supported CSS subset. Run your own documents through the benchmark before using these timings to estimate workload capacity.

Last updated on

On this page