Hacker News new | ask | show | jobs
by lewisjoe 820 days ago
This is an amazing piece of work. Thanks for making this open-source.

The default way of generating beautiful PDFs in the backend these days is, running a headless browser and using browser APIs to turn HTML/CSS into PDFs. And apparently, it's a bit costly running instances of browser in the server and scale it properly for huge workloads.

This is literally a game changer. Now it's possible to design PDFs using HTML/css and generate them without the browser overhead!

8 comments

As an aside its amazing how far the web has come, where the best way to make pretty pdf documents is to literally run a web browser on the server. This would have been so unthinkable back in the 90s & 2000s
I needed to transform a 12MB HTML file into a PDF document and headless Chrome quickly ran out of memory (4GB+).

We are now using a commercial alternative that seems be be using a custom engine that implements the HTML and CSS specs. The result is reduced memory usage (below 512MB during my tests) and the resulting PDF is much smaller, 3.3MB vs 42MB.

We use docraptor based on princexml engine but haven’t tried a huge pdf. We generate 20-30 page pdfs sometime and it works great.
We are also using DocRaptor. It takes around 20 seconds to generate the PDF, and we only need to generate it every night. So the costs are also not an issue at the moment.
Did you try Weasyprint?
Yes, I’ve tried all the open source projects I could find. Including Weasyprint and wkhtmltopdf. Weasyprint was much slower than headless Chrome and also required a lot of memory to process the HTML. And wkhtmltopdf is no longer maintained and crashed while processing.
Have you tried Typst? It's like a modern version of LaTeX and allows to generate nice looking documents quickly. Can be called from the console and makes it easy to create templates and import resources like images, fonts and data (csv, json, toml, yaml, raw files, ...). Of course it is its own language instead of HTML/CSS but so far I found it quite pleasant to use.
Back around 2002 at least there were some products, ABCpdf is one I used a lot, which ran Internet Explorer on the server to generate PDFs from HTML. Worked pretty well from what I recall.
I'm fairly certain that using a headless browser on the server is mainly about sandboxing all the security concerns that PDFs have, not aesthetics, but yes.
Security of the pdf format is not relavent here. The headless browser outputs a PDF. It is not taking a user controlled pdf as input.
Ah of course, my apologies. I misread the original post.
it's actually because layout-via-code for arbitrary documents is a humblingly complex problem, so leveraging existing layout engines is preferred.

This impressive effort looks far better than what I'd achieve, but when this approach has been tried before, it is eventually discovered that few organizations have the resources to maintain a rendering engine long-term.

I do think complexity could be part of why we don't have many options here, but I don't agree that a layout engine is too difficult to maintain. More of the issue is that CSS layout (and maybe layout in general) is not widely well-understood. I've almost _never_ come across people interested in layout because generally it's a few properties to get something working and then you move on.

> few organizations have the resources to maintain a rendering engine long-term

I'm curious are there other instances of this happening than Edge switching to Blink? That event was one of my main motivators; it felt like further consolidation of obscure knowledge.

Opera switched from Presto to Blink, too.

Very fun project! Did you ever consider integrating with web-platform-tests? It's shared between all the common browser vendors, and we're always interested in more contributors :-)

> Opera switched from Presto to Blink, too

True. But I wonder if there are more special-purpose engines similar to Prince that have been abandoned.

> Did you ever consider integrating with web-platform-tests?

I've run some of the WPT tests manually, but I don't yet have <style> support, and some of them use <script> I think? That's a path I'm wary of (eval()?) but I could have a special mode just for tests.

I did discover lots of weird corners that would be great to make some WPT tests for. Definitely something I want to do!

One of the benefits of using the browser is that the generated PDF will be using vectors/fonts etc whereas Canvas will be mostly an image in the PDF. Not a big deal for the most use cases.
I feel like it’s probably not a leap to go from this to having a PDF renderer as a backend. The trickiness is in the layout, which this is already doing. Looks to be a lower level api and a way to render to absolutely positioned html. That gets you most of the way there.
I've used this with good success

https://ekoopmans.github.io/html2pdf.js/

I've served dynamic content directly as PDF with https://xmlgraphics.apache.org/fop/
I'm a little confused by your comment. I've been using the Prawn library to generate PDFs on the backend for a side project I am working on for quite sometime https://github.com/prawnpdf/prawn

(Admittedly, the PDFs I generate are most certainly not beautiful, so maybe that's the difference)

> One thing Prawn is not, and will never be, is an HTML to PDF generator
Prawn really is great. I use it to generate invoices and for exporting a billing overview in client projects. And it’s quite fast as well, since it generates the PDF directly without the need to spin up a browser.
Lots of people are already really comfortable with html/css, so having the option to avoid learning an entirely new paradigm is helpful.
I've been building PDF renderers for a few clients. The biggest request in PDFs has been accessibility. Everyone needs to be ADA compliant. I sadly don't see myself switching to a canvas renderer because then there is no accessibility.
We did use this approach years back when I worked for on a feature that generated PDF invoices.

But I wondered whether using instead something like LaTeX wouldn't be faster and easier to scale.

I don't think rasterized output makes a good pdf.
You can make PDF client-side by html2canvas or webkit.js (https://github.com/trevorlinton/webkit.js)