Als u vandaag zocht op “Puppeteer PDF alternative” en hier terechtkwam, is de echte vraag waarschijnlijk een variant van:
“Waarom heeft mijn serverless functie 2 seconden cold start en 900 MB RAM nodig om één factuur te printen?”
Puppeteer is een uitstekend tool. Het is ook veel groter dan nodig voor de taak waarvoor de meeste teams het gebruiken: gestructureerde data omzetten naar een voorspelbare PDF. Deze post is voor het team dat op het punt staat Puppeteer naar productie te brengen en zich afvraagt of er een nuchterder alternatief is.
We behandelen waar Puppeteer zijn gewicht verdient, waar niet, en hoe de werkelijke trade-offmatrix er in 2026 uitziet.
Wat u werkelijk shipt met Puppeteer
Wanneer u npm install puppeteer uitvoert, haalt u vóór transitieve dependencies al een Chromium-build van ongeveer 170 MB binnen. Tijdens runtime heeft Chromium zonder UI voor één paginarender vaak 600-900 MB resident geheugen nodig, plus 1-2 seconden cold start om de browser te starten. Elke render moet:
- Het browserproces starten, of een pool hergebruiken
- Een nieuw tabblad openen
- Naar uw HTML/URL navigeren
- Wachten op
domcontentloaded, en meestal ook op fonts, afbeeldingen en webcomponenten page.pdf()uitvoeren, waarbij de geschilderde pagina via de PDF-engine van Chromium wordt geserialiseerd- Het tabblad sluiten
Dit is de belasting van het hele webplatform. U betaalt die zowel voor een juridisch contract van 90 pagina’s met ingesloten SVG-grafieken als voor een verzendetiket van één pagina met vijf regels tekst.
Voor HTML-naar-PDF use-cases waarbij de invoer werkelijk CSS-layout, JavaScript-gestuurde content, webfonts en de rest van het webplatform nodig heeft, is die belasting terecht. Voor al het andere, zoals facturen, etiketten, bonnen, tickets, overzichten en certificaten, is het vaak geld verbranden.
Waar Puppeteer wint
Wees hier eerst eerlijk over, anders gaat het team de keuze later opnieuw ter discussie stellen:
- Getrouwe HTML/CSS-rendering. Als uw designsysteem HTML produceert en u pixelidentieke PDF’s van die HTML wilt, is Puppeteer moeilijk te verslaan. Het is letterlijk Chrome die print.
- Webplatformfeatures. SVG met filters, CSS Grid-randgevallen, webcomponenten, JavaScript-geëvalueerde content en iframes van derden werken gewoon.
- Visueel debuggen. U kunt halverwege de render een screenshot nemen, DevTools openen tegen de browser zonder UI en precies zien wat de renderlaag ziet.
- Geen vertaalslag. Als uw content al een webpagina is, is er geen schema-mapping.
page.goto(url); await page.pdf()is het hele proces.
Als twee van deze punten uw echte workload beschrijven, stap dan niet over. Puppeteer is dan het juiste antwoord.
Waar Puppeteer hard verliest
Voor alles daarbuiten stapelt de kostenlaag snel op.
Geheugen en cold start in serverless
Een typische Node 20 Lambda of Cloudflare Container met Puppeteer:
| Metriek | Typische waarde |
|---|---|
| Container-imagegrootte | 250-400 MB (Chromium + Node + uw code) |
| Cold-starttijd | 1,8-2,5 seconden |
| Warm RAM per render | 600-900 MB |
| Gelijktijdige renders per 1 GB-instantie | 1 (soms 2 als pagina’s klein zijn) |
Als uw factuurservice 100.000 renders per maand verwerkt, betaalt u voor browserstartenergie bij elke koude container, ook al had geen van die renders JavaScript-uitvoering nodig.
De font-val in containers
Chromium wordt geleverd met een standaard fontset, waarin meestal CJK, Cyrillisch, Devanagari, Arabisch en een lange reeks scriptspecifieke glyphs ontbreken. In productie ziet zo’n ontdekking er als volgt uit:
De Q3 2025-factuur voor het kantoor in Tokio print
▢▢▢▢ 2025年第3四半期. De klant escaleert. Uw team besteedt een sprint aan Dockerfile-fontinstallaties en CSS-fontfallbacks.
Alleen NotoSans CJK toevoegen vergroot de image met ~50 MB. Een wereldwijde Noto-fallbackset toevoegen kan ~250 MB kosten. U betaalt dan voor Chromium én een kathedraal aan fonts, alleen om één Japanse factuur te printen.
Determinisme
Puppeteer-renders zijn niet byte-identiek tussen Chromium-versies. Een patchupgrade kan kerning, fontbaselines of paginabreaks subtiel verschuiven. Als u een testsuite hebt die PDF’s difft, en dat zou u moeten hebben, wordt elke Chromium-update een klein onderzoek: welke rendering veranderde, en was dat de bedoeling?
JavaScript tijdens renderen
Zelfs een “statische” HTML-pagina moet worden geparst, gelayout, geschilderd en geserialiseerd. In de praktijk kost dat op een warm proces 80-400 ms per pagina. Het meeste daarvan is layout, niet paint.
Ter vergelijking: een server die JSON direct aan een binaire renderengine geeft, kost 3-8 ms voor dezelfde factuur van één pagina. Hieronder komen die cijfers terug.
Waar gPdf past
gPdf draait het model om: in plaats van het document als HTML te beschrijven en een browser te vragen het te schilderen, beschrijft u het als gestructureerde JSON (een DocumentRequest) en schrijft een Rust-renderengine, gecompileerd naar WebAssembly, de PDF direct uit. Er is geen browser. Er is geen DOM. Er is geen JavaScript-layoutpass.
Dat klinkt beperkend, en dat is het ook voor problemen die echt HTML-vormig zijn. Maar voor de documentklasse factuur / etiket / bon / overzicht / certificaat past het JSON-first model juist beter:
- De data is al gestructureerd. Uw factuur leeft meestal al ergens als
{ customer, lines, totals, taxes, notes }. U wilt die niet eerst naar HTML renderen en daarna een browser vragen die HTML weer terug te lezen als layout. U wilt direct van data naar PDF. - Layout wordt een contract. Wanneer
font_size: 11altijd 11 punten betekent engap: 8altijd 8 punten, zien twee engineers die een PR reviewen exact dezelfde output. Er is geen interpretatieverschil ronddisplay: flex. - Output is byte-identiek. Zelfde invoer → zelfde bytes. U kunt twee PDF’s diffen en alleen zien wat werkelijk veranderde.
- Cold start is runtime-start, geen browserstart. Een V8-isolate op Cloudflare Workers initialiseert in 5-20 ms. De WASM-module blijft op dezelfde isolate warm in geheugen.
Een typische gPdf-render van een factuur van één pagina klokt 3-5 ms p50 wall-clock op de edge, bediend vanuit de Cloudflare-colo die de gebruiker raakt. Dat is ongeveer twee ordes van grootte sneller dan het warme pad van Puppeteer, en drie ordes van grootte sneller dan het koude pad.
De beslismatrix
Gebruik de tabel die u ook in een technische designreview zou gebruiken.
| Workload | Kies Puppeteer | Kies gPdf |
|---|---|---|
| Bestaand HTML-rapport → PDF | ✅ eerste keuze | ⚠️ vereist herschrijven |
| Facturen, overzichten, bonnen | ⚠️ zware hamer | ✅ eerste keuze |
| Verzendlabels met barcodes | ❌ vermijden (fontproblemen) | ✅ eerste keuze |
| E-factuur (Factur-X / ZUGFeRD / EN 16931) | ❌ geen ingebouwde ondersteuning | ✅ ingebouwd |
| PDF/A voor langetermijnarchief | ⚠️ vereist Ghostscript-pass | ✅ ingebouwde profielen |
| Pixelgetrouwe mockups uit een designsysteem | ✅ eerste keuze | ❌ verkeerde tool |
| Grafieken die echte D3 / Recharts nodig hebben | ✅ eerste keuze | ❌ verkeerde tool |
| Tickets, certificaten, naamkaartjes | ⚠️ overkill | ✅ eerste keuze |
| Alles wat JavaScript nodig heeft tijdens renderen | ✅ enige keuze | ❌ verkeerde tool |
Als u op meer dan drie rijen in de rechterkolom zit, is de besparing niet subtiel.
Een echte vergelijking: factuur van één pagina
Dezelfde content. Hetzelfde papierformaat. Dezelfde fonts (NotoSans). Hetzelfde PDF/A-3b-profiel.
| Puppeteer (warme Lambda, 1 GB) | gPdf (warme Cloudflare Worker) | |
|---|---|---|
| p50-latency | 180 ms | 3,4 ms |
| p99-latency | 420 ms | 8 ms |
| Cold-startpenalty | +1800 ms eerste render | +12 ms eerste render |
| Piekgeheugen | 720 MB | 18 MB |
| Image-/modulegrootte | 280 MB | 4,5 MB |
| CJK-glyphs | ❌ tenzij expliciet geïnstalleerd | ✅ embedded NotoSans CJK |
| Kosten per 100.000 renders | ~240 USD (Lambda-compute) | ~5 USD (gPdf Basic-plan) |
Die laatste rij verrast vaak. Het kostenverschil is echt, en het is geen lokprijs. Het is structureel. We hoeven geen Chromium-start, browsergeheugen of container-cold-starts af te schrijven, dus de eenheidskosten per render zijn werkelijk klein.
“Maar 5 USD per 100.000 pagina’s klinkt te goedkoop. Waar zit de adder?”
De adder is precies dat we geen browser leveren. De kosten van een binaire renderengine op een warme V8-isolate zijn milliseconden CPU en kilobytes geheugen. Puppeteer-vormige prijzen vragen zou betekenen dat we infrastructuur doorbelasten die we niet draaien.
Wanneer u toch Puppeteer moet kiezen
We zouden de slechtste adviseur zijn als het antwoord altijd “gebruik gPdf” was. Dat is het niet. De eerlijke gevallen:
-
U draait Puppeteer al in productie en het werkt. Migreer niet voor de sport. Het juiste moment om gPdf te evalueren is wanneer Puppeteer pijn doet, meestal wanneer maandelijkse compute-rekeningen boven 400 USD komen of wanneer cold-start-SLA’s iets downstream breken.
-
Uw documenten zijn bestaande webpagina’s, punt. Een door gebruikers gemaakt rapport van 60 pagina’s, gestyled door uw designsysteem, met geneste grafieken en dynamische content, is geen JSON-migratie. Dat is een herontwerp.
-
U hebt pixelperfecte gelijkheid met een webpreview nodig. Sommige processen, bijvoorbeeld “wat u in de editor ziet, is wat er wordt geprint”, hebben Chromium werkelijk nodig als renderlaag aan beide kanten.
Als geen van deze gevallen geldt, is de rekensom helder: kleinere deploy, lagere latency, lagere rekening, byte-identieke output en geen fontinstallatiedrama.
Een echte workload migreren
Als u genoeg overtuigd bent om het te proberen, is de migratie meestal een spike van 1-2 dagen per documenttype, geen herarchitectuur:
- Kies één document, te beginnen met het hoogste volume en niet met het meest complexe.
- Map de logische secties van uw HTML-template naar gPdf JSON-elementen (
text,box,table,barcode,image). - Gebruik de Playground om met een echte
DocumentRequestte itereren tot de output overeenkomt. - Sluit uw bestaande datavorm aan op een kleine mapperfunctie die de JSON uitstoot.
- Draai een week A/B met de nieuwe API-route naast uw Puppeteer-route. Diff de PDF’s. Beslis.
De meeste teams merken dat het JSON-model binnen een dag klikt. Het moeilijke is niet de nieuwe tool, maar het ontwarren van de HTML/CSS-gymnastiek die het oude template in de loop der tijd heeft opgebouwd.
TL;DR
Puppeteer is het juiste antwoord voor webpagina’s. Voor documenten betaalt u bij elke render een 100-200x kostenlaag om de kleine eenmalige stap te vermijden waarin u het document als data beschrijft. Als uw fleet facturen, etiketten, bonnen, overzichten, tickets of andere documenten rendert met “dezelfde vorm, andere waarden”, is een edge-native renderengine zoals gPdf meetbaar sneller, kleiner, goedkoper en deterministischer.
Probeer het in de Playground: een echte edge worker, geen signup, response in uw browser in minder dan 5 ms.