Converting HTML template to PDF using NodeJs

Hardeek Sharma
4 min readDec 24, 2019

--

Its has always been a challenge for many developers to generate PDF from html on server side.

There are scenarios like where we need to generate a PDF invoice for a customer, save it on server as well as email them the PDF.

I have uploaded the code on my GIT HUB repository.

How is this possible?

It was a pickle for me till I came to know about puppeteer.

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the Dev Tools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

Well, to be true puppeteer is way worth more than just creating PDF. Its for you to explore, for this tutorial we are going to use it just to create a PDF of an HTML template invoice.

For ease of beginners I am using a simple invoice html template I found on GitHub.

We’ll be using some Node packages like handlebars and puppeteer obviously.

I am using v12.13.0 of NodeJs. You can use 10+ version for ease of development.

I am assuming readers have basic knowledge of NodeJs to setup a basic project using npm init if not be a good student and google it.

Now its time to install dependencies we need. Install both handlebars and puppeteer in your node project using the command below.

npm i handlebars puppeteer

This will take some time to get installed as its 150Mb+ package. So have patience and go get some thing to eat.

After both the packages are installed your package.json should have an object that looks like this.

"dependencies": {
"handlebars": "^4.5.3",
"puppeteer": "^2.0.0"
}

Versions may vary as per the time you are reading this. You can check latest updates and changes here at official puppeteer website.

HTML template must look like this.

NOW THE CODE

const fs = require('fs')const path = require('path')const utils = require('util')const puppeteer = require('puppeteer')const hb = require('handlebars')const readFile = utils.promisify(fs.readFile)
async function getTemplateHtml() {console.log("Loading template file in memory")try {const invoicePath = path.resolve("./invoice.html");return await readFile(invoicePath, 'utf8');} catch (err) {return Promise.reject("Could not load html template");}
}
async function generatePdf() {let data = {};getTemplateHtml().then(async (res) => {// Now we have the html code of our template in res object// you can check by logging it on console// console.log(res)console.log("Compiing the template with handlebars")const template = hb.compile(res, { strict: true });// we have compile our code with handlebarsconst result = template(data);// We can use this to add dyamic data to our handlebas template at run time from database or API as per need. you can read the official doc to learn more https://handlebarsjs.com/const html = result;// we are using headless modeconst browser = await puppeteer.launch();const page = await browser.newPage()// We set the page content as the generated html by handlebarsawait page.setContent(html)// We use pdf function to generate the pdf in the same folder as this file.await page.pdf({ path: 'invoice.pdf', format: 'A4' })await browser.close();console.log("PDF Generated")}).catch(err => {
console.error(err)
});
}
generatePdf();

To run above code run the command node index.js

After successful execution of the above code you see message on command prompt like this.

And you will see a file named invoice.pdf generated in you project folder.

Thank you all for reading my second article on medium. I know it may be not perfect but I am continuously improving my article quality.

CRITICISM IS MOST WELCOME AND APPRECIATED

--

--

Hardeek Sharma

Software Developer. Java & java script enthusiast. Spring boot, Angular 4+, VueJs, NodeJs developer.