Navigating the PDF Generation Maze: A Journey from jsPDF to Chrome

February 12, 2025, 10:10 pm
npm support
npm support
Location: United States, California, Oakland
Employees: 11-50
Founded date: 2009
Total raised: $8M
In the world of web development, generating PDFs from HTML can feel like navigating a labyrinth. Each turn presents new challenges, and the exit often seems elusive. This article explores a real-world case study of creating PDFs from an Ant Design-based HTML page, revealing the trials and triumphs along the way.

The project aimed to produce legal documents, which are crucial for maintaining records. These documents could stretch up to a hundred pages, primarily filled with tables and dense text. The need for accuracy was paramount. Any discrepancies could lead to legal complications.

Initially, two methods were in place: one using Chrome and the other an unfinished solution with jsPDF. The first hurdle was the Cyrillic fonts. jsPDF struggled with them, generating PDFs with garbled text. The library offered a font converter, but it was a dead end. The fonts simply didn’t support Cyrillic characters. After much back and forth, new fonts were acquired and successfully converted. A small victory, but the road ahead was still fraught with obstacles.

Next came the issue of text being cut off in tables. jsPDF had a knack for splitting rows in half, creating a jigsaw puzzle of missing information. While the client was initially satisfied with the generated PDFs, the requirement soon shifted. They needed server-side PDF generation, which meant a new approach was necessary.

The backend developer pivoted to using wkhtmltopdf, a utility that converts HTML to PDF. The results were visually appealing, but the client demanded that the PDF match the on-screen display precisely. This was no small feat. The challenge lay in the fixed A4 format, which often led to text shifting and misalignment when viewed on different screens.

To address this, a compromise was reached: two display modes. One for editing and another for PDF generation. This required sending the HTML and CSS to the server, which was no trivial task. The content could balloon to 100 pages, necessitating compression techniques to minimize data transfer.

However, wkhtmltopdf had its own set of problems. The version in use clipped text at page breaks and misrepresented table styles. This led to a search for alternatives. Prince was quickly dismissed due to its cost. WeasyPrint initially seemed promising but soon revealed its own flaws. It struggled with CSS styles and occasionally omitted text in tables.

Then came Puppeteer, a Node.js library that controls headless Chrome. It rendered tables flawlessly and supported the latest CSS styles. It appeared to be the golden ticket. But there was a catch: the project didn’t use Node.js, and deploying a container solely for PDF generation was a no-go.

The search continued. Why did most utilities falter with tables? The answer lay in their reliance on Qt Webkit, which struggled with rendering. Puppeteer, leveraging headless Chrome, stood apart.

Returning to the drawing board, the solution emerged: using Chrome directly. By diving into the documentation, the right parameters for PDF generation were uncovered. A simple command line could generate the desired output.

Yet, a new issue arose: unwanted headers and footers in the PDF. The solution was to disable them using a specific command. The final touch involved adding page numbers, which required a combination of LaTeX and pdftk.

The process unfolded in several steps. First, the necessary packages were installed. Then, a LaTeX template was created to handle pagination. The final PDF was a masterpiece, beautifully rendered and correctly numbered.

In conclusion, while the journey from jsPDF to Chrome was fraught with challenges, it underscored a vital lesson: sometimes, the simplest solutions lie in the most familiar tools. The complexities of PDF generation can be daunting, but with persistence and creativity, even the most tangled problems can be unraveled.

This case study serves as a reminder that in the world of development, adaptability is key. While libraries like jsPDF and WeasyPrint have their merits, sometimes the best path forward is to return to the basics. The tools may change, but the goal remains the same: delivering accurate, reliable results.

For those embarking on similar journeys, remember: every challenge is an opportunity to learn. Embrace the process, and you may just find the solution waiting at the end of the maze.