High-quality pdf generation using puppeteer

Written by iamnowshad | Published 2019/02/06
Tech Story Tags: javascript | chrome | nodejs | programming | development

TLDRvia the TL;DR App

And how I used it to make a resume!

Backstory

I was looking for a free resume builder. Though I was using Novoresume free scheme before, it was not enough as I couldn’t customize most of the things. Also, their paid schemes are pretty expensive. So, as a web developer, I just coded my own resume builder with HTML + CSS 🎉

Now, as I wanted to print the resume as PDF I faced a challenge. Using Google Chrome’s default print command on any web page generated not so high-quality pdf as the dpi is low.

Searching through pdf generators in JS I couldn’t find any good source which could generate accurate pdf to my HTML with links, images, styling, etc. Puppeteer came to the rescue. It can take a snapshot or generate the exact pdf output of any webpage !!!

Let's make a webpage

This is a sample resume I made with HTML + CSS which I used ReactJS to build as it gives me more power to use js for repeating patterns and component architecture. But, a plain .html file is also fine for the purpose.

If we use the chrome print command (`CTRL+P`) to print this page and save as pdf, we’ll see that the pdf is not high quality! It’s because of Chrome's default resolution and 72dpi setup for printing.

Using Puppeteer

  • We need NodeJS installed on our machine.

Let’s see both react and non-react version

ReactJS

Suppose our resume page is running on port 3000 and available at [http://localhost:3000](http://localhost:3000).

Now, as we’re already inside a react project and we have a package.json file in our project, let’s just install puppeteer first with the command below -

npm install --save puppeteer

Line 1: We’re loading puppeteer.

Line 4: Initializing a browser (we can think this as opening a new chrome window).

Line 5: Opening a new page (we can think this as opening a new chrome tab).

Line 6: Setting the viewport’s width and height. deviceScaleFactor is by default 1, we’re doubling it so that the quality of the output gets better.

Line 7: Visit localhost:3000, wait until everything is loaded properly with networkidle2

Line 8–13: Generate a .pdf file named resume.pdf with A4 paper size in the current directory. Set printBackground to true to print background colors and styling. pageRanges makes sure we’re getting only the first page (we could avoid it if we had a multipage resume).

Line 15: Closing the browser as the work has been finished.

Now, let’s create a file named generatePDF.js with the code above, in our project’s root folder and run the command below -

node generatePDF.js

This will generate a resume.pdf file in the same directory. Now if we open up the pdf file with a pdf viewer, we can see that the pdf is better in quality than the directly printed one from the browser (ctrl+p).

Using Plain HTML file

We need to change only Line 7 from the ReactJS version

await page.goto("file://practice/resumeapp/resume.html",{ waitUntil: "networkidle2" });

But, as we have no node/react project setup for this plain HTML version let’s just create one.

mkdir resumeappcd resumeapp

This will create a directory named resumeapp and take you into the directory.

npm init --yes

This will initialize a package.json file in your directory. Now let’s install puppeteer -

npm install --save puppeteer

Now let’s create a file named generatePDF.js with the code below -

Make sure your resume.html file’s path is correct. Now, run the command below in the same shell/directory.

node generatePDF.js

This will generate a resume.pdf file in the same directory. Now if we open up the pdf file with a pdf viewer, we can see that the pdf is better in quality than the directly printed one from the browser (ctrl+p).

This pdf generation trick can be pretty handy as using puppeteer enables us to use chrome’s awesome features in the backend. We can take screenshots, make books from crawled data, and what not! The possibilities are endless and that’s for you to explore.

Good Luck 🙂


Published by HackerNoon on 2019/02/06