MODULE: Generate PDF from EJS Template with Puppeteer

First and foremost, a lot of credit has to go to @sid. Their module for HTML to PDF was the basis of this one.

SO WHY CREATE ANOTHER PDF MODULE?

The reasoning here was to make it easier to generate a bank of EJS templates that you could visually build, add JSON data to, and dynamically generate the resulting HTML.

My first thought, when using @sid’s module was to plug my routes into Puppeteer, however, along with this came the problems of security enforcers forcing Puppeteer to login in (which is correct, because Puppeteer is another browser instance, thus, another session). Then came the issues on how to secure the login information or session cookies to automate this process.


PREREQUISITES

  1. You will need to add Puppeteer to your project and allow it to download the required version of Chromium it needs to run.
    npm install puppeteer

  2. Obviously, you will need the module. I’ll eventually get around to adding a GIT repository with a demo project when I can find the time. For now, you can find the 2 module files below plus the example EJS template that you’ll see the output of further down.
    EJS to PDF - Git Repository

  3. Get a quick rundown on EJS templating language.

  4. The system I am running on, which is the only system I have checked this module with, is a Docker container running Node v14 server.

HOW TO USE

Adding the module.

  1. Add the two module files into your extensions/server_connect/modules folder. If you already have Wappler open, you’ll need to restart. Just right click the taskbar icon and restart Wappler.

  1. You can now find the module under File Management named EJS to PDF.

Creating the Data

  1. Set up a new Library Action that you can call on inside your API Action. Ensure you have your POST variables set. This will output the data you need in your EJS template. Make sure you take note on the structure of the data being outputted by this action. This will become important when you create your EJS template. As always, you can always check the output in DevTools to check the structure.

  1. Include your library action in your API. Your API will need the same $_POST variables you set up in the last step.

  1. Puppeteer needs absolute paths to your images, css files, js files etc. Therefore you need create a $_POST variable named host that you pass into your action.

    If you’re using Docker, you will need to find the hostname of your container. Open the WebServer terminal in Wappler and type hostname -f. The output is your hostname.

    I use the following AppConnect binding from a Browser element on my page in a hidden input to get the full host. browser.location.protocol+'//'+browser.location.host

  1. Add a conditional and set values in your API as above. The set values all have “host” as the Name and Global Name.

    This conditional is checking whether the action is running on the development server on in a production environment. If you’re in production and using a Docker container, you may still need to use the Docker hostname and not your https://example.com hostname. I’ve not tested this, and am pretty crap at Docker, so I’m unsure.

Generating the PDF.

  1. Add the EJS to PDF module in your API.

  1. Set your values:

TEST YOUR NEW ACTION

First, here’s the output from DevTools.

And here’s the PDF output. (Don’t mind Willy Nelson. :rofl:)

DOCKER

Dockerfile

With Puppeteer, you’ll need to add the following code to your Dockerfile underneath COPY package.json .

## PUPPETEER INSTALL ##
RUN apt-get update
&& apt-get install -y wget gnupg
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
&& sh -c ‘echo “deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main” >> /etc/apt/sources.list.d/google.list’
&& apt-get update
&& apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1
–no-install-recommends
&& rm -rf /var/lib/apt/lists/*
## END PUPPETEER INSTALL ##

Hostname

Personally, I have changed the default hostname of the Docker container so I can rely on what the hostname is going to be during the conditional we added into our API above. I added the following to the docker-compose.yml under the line tty: true

hostname: ssacrm

Rebuild Docker Container

Any changes to the Docker configurations, you’ll need to rebuild the container. Just hit the Deploy button in Wappler and you’re ready to go.


I hope this all helps. Let me know if you run into any problems. I’m not the best at troubleshooting for others, but I’ll give it a red hot crack. I’ve got to be off for the weekend now, but I’ll respond as soon as I can.

Once again. Thanks to @sid for the basis of this module.

Cheers everyone.
-Michael.

Community Page
Last updated: