GENERATE PDF with Puppeteer + Handlebars

gabrielqueirozdev

Gabriel de Paula Queiroz

Posted on February 7, 2023

GENERATE PDF with Puppeteer + Handlebars

In this tutorial, we are going to learn how to generate a PDF using an API.

For this, we will use the following libs

Let's use the lib https://www.npmjs.com/package/puppeteer, which is a chromium for us to manipulate our HTML

We will also use the Handlebars lib https://www.npmjs.com/package/handlebars, which is basically a template compiler.

So the first step is to install these libraries, for that just run



npm install puppeteer handlebars

// or if you are using yarn

yarn install puppeteer handlebars


Enter fullscreen mode Exit fullscreen mode

After installing the libraries, we will create a controller in our API by starting the puppeteer configuration.



class PDFController {

async index(_: Request, response: Response) {
    // Defines the name of the PDF
    const name = 'nodejs-pdf-example.pdf';

    let configLaunch = {
        headless: true, // headless: 
Informs whether the browser should run headless, that is, without a graphical interface
        ignoreDefaultArgs: ['--disable-extensions'],
    };

    // Start the puppeteer
    const browser = await puppeteer.launch(configLaunch);

    // Open new page
    const page = await browser.newPage();
    const waitUntil = 'networkidle2';
}

export default new PDFController();


Enter fullscreen mode Exit fullscreen mode

Now, let's add our HTML, which will serve as the base of our PDF



...
    // getting the template
    const templateDir = resolve(__dirname, '..', 'views', 'template-pdf.hbs');
    const file = fs.readFileSync(templateDir, 'utf-8');

    // compiling
    const fileCompiled = Handlebars.compile(file);

    // getting the template in string
    const fileHTML = fileCompiled({})
... 



Enter fullscreen mode Exit fullscreen mode

After that, let's integrate our HTML with the puppeteer. The puppeteer has his own method to generate the pdf.



    await page.setContent(fileHTML, {
        waitUntil,
    });

    await page.setDefaultNavigationTimeout(0);

    // generate PDF
    await page.pdf({
        format: 'A4',
        path: `tmp/${name}`,
        displayHeaderFooter: false,
        preferCSSPageSize: false,
        printBackground: true,
    });

    await browser.close();
    const pdfFile = fs.readFileSync(`tmp/${name}`);

    // Removing PDF file from the temp folder
    fs.unlinkSync(`tmp/${name}`);

    // return the PDF
    response.contentType('application/pdf');
    response.send(pdfFile);


Enter fullscreen mode Exit fullscreen mode

And the complete code should look like this:



import { Request, Response } from "express";
import puppeteer from "puppeteer";
import fs from 'fs'
import { resolve } from "path";
import Handlebars from "handlebars";

class PDFController {
async index(_: Request, response: Response) {
    const name = 'nodejs-pdf-example.pdf';

    let configLaunch = {
        headless: true, 
        ignoreDefaultArgs: ['--disable-extensions'],
    };

    const browser = await puppeteer.launch(configLaunch);

    const page = await browser.newPage();
    const waitUntil = 'networkidle2';

    const templateDir = resolve(__dirname, '..', 'views', 'template-pdf.hbs');
    const file = fs.readFileSync(templateDir, 'utf-8');
    const fileCompiled = Handlebars.compile(file);
    const fileHTML = fileCompiled({})

    await page.setContent(fileHTML, {
        waitUntil,
    });

    await page.setDefaultNavigationTimeout(0);

    await page.pdf({
        format: 'A4',
        path: `tmp/${name}`,
        displayHeaderFooter: false,
        preferCSSPageSize: false,
        printBackground: true,
    });

    await browser.close();
    const pdfFile = fs.readFileSync(`tmp/${name}`);

    fs.unlinkSync(`tmp/${name}`);

    response.contentType('application/pdf');
    response.send(pdfFile);
}

export default new PDFController();


Enter fullscreen mode Exit fullscreen mode

folders

Hope I was able to help!

The full project directory is at: https://github.com/gabrielqueirozdev/nodejs-pdf-example

If you have any suggestions for improvement, please contact me.

👋🏼

💖 💪 🙅 🚩
gabrielqueirozdev
Gabriel de Paula Queiroz

Posted on February 7, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

GENERATE PDF with Puppeteer + Handlebars
puppeteer GENERATE PDF with Puppeteer + Handlebars

February 7, 2023