avatarAndréas Hanss

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

8029

Abstract

<span class="hljs-attr">height</span>: <span class="hljs-number">300</span>, <span class="hljs-attr">ellipsis</span>: <span class="hljs-literal">true</span> });</pre></div><div id="5236"><pre><span class="hljs-comment">// end and display the document in the iframe to the right</span> doc.<span class="hljs-keyword">end</span>(); stream.<span class="hljs-keyword">on</span>(<span class="hljs-string">'finish'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> <span class="hljs-comment">{ iframe.src = stream.toBlobURL('application/pdf'); }</span>);</span></pre></div><p id="11d4">Alright! Great! It’s just a matter of sequencing imperative instructions, but that’s all, a kind of low-level API. Do you need custom charts? You’ll need to make your own with SVG and something like <a href="https://d3js.org/">d3-js</a>.</p><p id="8449">As it’s imperative and especially low API it can take some time to achieve the expected final results and it might require a lot of code. You’ll probably need some 2D modelization using the Vectors to draw what you need and the tool won’t help you with that.</p><p id="7494">If you’re using React JS you can achieve something similar with a declarative wrapper that provides a bit higher tier components.</p><h2 id="654d">Using ReactJS</h2><p id="feb4">The best tool on the React context is <a href="https://react-pdf.org/">https://react-pdf.org/</a> it allows you to design PDF using React components and use some kind of CSS language for the layout, which is great.</p><div id="5fbb"><pre><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>; <span class="hljs-keyword">import</span> { Page, <span class="hljs-type">Text</span>, <span class="hljs-keyword">View</span>, Document, StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'@react-pdf/renderer'</span>;</pre></div><div id="2411"><pre><span class="hljs-comment">// Create styles</span> <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">styles</span> = StyleSheet.<span class="hljs-title function_ invoke__">create</span>({ <span class="hljs-attr">page</span>: { <span class="hljs-attr">flexDirection</span>: <span class="hljs-string">'row'</span>, <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'#E4E4E4'</span> }, <span class="hljs-attr">section</span>: { <span class="hljs-attr">margin</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">padding</span>: <span class="hljs-number">10</span>, <span class="hljs-attr">flexGrow</span>: <span class="hljs-number">1</span> } });</pre></div><div id="741d"><pre><span class="hljs-comment">// Create Document Component</span> <span class="hljs-keyword">const</span> <span class="hljs-title function_">MyDocument</span> = (<span class="hljs-params"></span>) => ( <span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">Document</span>></span> <span class="hljs-tag"><<span class="hljs-name">Page</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"A4"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.page}</span>></span> <span class="hljs-tag"><<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.section}</span>></span> <span class="hljs-tag"><<span class="hljs-name">Text</span>></span>Section #1<span class="hljs-tag"></<span class="hljs-name">Text</span>></span> <span class="hljs-tag"></<span class="hljs-name">View</span>></span> <span class="hljs-tag"><<span class="hljs-name">View</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{styles.section}</span>></span> <span class="hljs-tag"><<span class="hljs-name">Text</span>></span>Section #2<span class="hljs-tag"></<span class="hljs-name">Text</span>></span> <span class="hljs-tag"></<span class="hljs-name">View</span>></span> <span class="hljs-tag"></<span class="hljs-name">Page</span>></span> <span class="hljs-tag"></<span class="hljs-name">Document</span>></span></span> );</pre></div><p id="143c">Alright, this is a bit better and dead simple isn’t it? It’s also easier to maintain as it uses kind of JSX instructions and components which are a great way to split our interface.</p><p id="fe7f">But it comes with the same issues. It remains still low tier and also relies on canvas for specifics needs such as charts. Here again, you’ll need some external library.</p><p id="c9bc">Under the hood react-pdf uses PDFKit.</p><p id="6563">For frontend in JavaScript, I guess tools based on PDFKit are the only viable tools but I might have lacked somethings, feel free to reach me if you have a higher level API with better support :)</p><p id="63f9">We’ll see one more on the frontend side a bit further in that article as it’s also a cross-platform tool :)</p><h1 id="055b">Or should I build PDFs on Backend / Server with NodeJS or Cloud Function?</h1><p id="062c">In that case, every logic is delegated to the server that will own everything to render our PDF and sent it to the client application.</p><p id="cf2a"><b>✅ Using backend PDF generation has various benefits:</b></p><ul><li>It gives more capabilities of making PDFs as you can rely on some existing binary from other languages and specialized in PDFs generation.</li><li>You have more control over everything such as access control policies as it’s server authority, you could just cut off access if the user hasn’t paid for example.</li><li>You can use a third-party service and control access and usage on it.</li><li>You can ensure that the results will be the same on all devices, as you control the execution environment. When using backend you generally ensure consistency between client platforms.</li></ul><p id="9526"><b>❌ But it also has this amount of cons:</b></p><ul><li>As the main drawback, you need an internet connection on the frontend.</li><li>You need a backend that will cost some every month. A backend that you might need to scale depending on frequentation.</li><li>If the backend fall, the feature falls whereas in frontend integration everything would have still worked.</li><li>It could also be less secure because you might need to send user information to the backend that he doesn’t already collect for other purposes.</li></ul><h2 id="0b20">Choosing the proper environment for backend PDFs generation</h2><p id="258a">Before building PDFs on the backend, you must be aware of your environment and shipped library. As an example, you can’t use everything in a cloud function environment because it might lack some binaries.</p><ul><li>Do I have a Ubuntu Linux, CentOS, or even Windows server?</li><li>Is my code running on a barebone server or inside of a cloud function?</li><li>What are my RAM and Processor capabilities?</li></ul><p id="852b">Here are some questions you should ask yourself. With that in mind, there are various ways of building PDFs on the server-side.</p><p id="d462">Some about HTML and are very useful for small use cases. Others are about bare-bone PDFs clients, which are way harder but also more efficient for complex use cases.</p><p id="c165">You can even rely on an external service such as SAAS software.</p><h2 id="6c85">Using Puppeteer to generate PDFs on the backend side</h2><p id="1d9f">Puppeteer is supposed to be a headless client for chromium-based browsers, it is made by Google engineers. You are writing code that drives the browser on some pages or inject some HTML into the browser, then you can interact with the HTML document.</p><p id="c01e">Therefore, you’ll use the functionality <code>save to PDF</code> of the browser, that way all you have to do is to design a page with CSS specific for your print or add a CSS print sheet.</p><p id="e43c">We

Options

end up with a code like this:</p><div id="b359"><pre><span class="hljs-attribute">const chromium</span> = require(<span class="hljs-string">'chrome-aws-lambda'</span>);</pre></div><div id="bd05"><pre><span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> (req, res) => { <span class="hljs-keyword">let</span> result = <span class="hljs-literal">null</span>; <span class="hljs-keyword">let</span> browser = <span class="hljs-literal">null</span>;</pre></div><div id="ae89"><pre><span class="hljs-keyword">try</span> { browser = await chromium.puppeteer.<span class="hljs-title function_ invoke__">launch</span>({ <span class="hljs-attr">args</span>: chromium.args, <span class="hljs-attr">defaultViewport</span>: chromium.defaultViewport, <span class="hljs-attr">executablePath</span>: await chromium.executablePath, <span class="hljs-attr">headless</span>: chromium.headless, <span class="hljs-attr">ignoreHTTPSErrors</span>: <span class="hljs-literal">true</span>, });</pre></div><div id="e986"><pre>let page <span class="hljs-operator">=</span> await browser.newPage()<span class="hljs-comment">;</span></pre></div><div id="43b7"><pre><span class="hljs-keyword">await</span> page.<span class="hljs-keyword">goto</span>(<span class="hljs-string">'https://example.com'</span>);</pre></div><div id="61e8"><pre><span class="hljs-keyword">const</span> pdfBuffer = <span class="hljs-function">await page.<span class="hljs-title">pdf</span><span class="hljs-params">({ printBackground: <span class="hljs-keyword">true</span> })</span></span>;</pre></div><div id="e32e"><pre>res.<span class="hljs-keyword">set</span>(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"application/pdf"</span>); res.<span class="hljs-keyword">set</span>(<span class="hljs-string">"Content-Disposition"</span>, 'attachment; <span class="hljs-keyword">filename</span>=<span class="hljs-string">"My-report.pdf"</span>'); res.status(<span class="hljs-number">200</span>).send(pdfBuffer); } <span class="hljs-keyword">catch</span> (<span class="hljs-keyword">error</span>) { <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).send(<span class="hljs-keyword">error</span>); } finally { <span class="hljs-keyword">if</span> (browser !== null) { await browser.<span class="hljs-keyword">close</span>(); } } };</pre></div><p id="21dc"><b>This is great, but let’s be honest kind of hacky.</b></p><p id="51c2">Speaking of difficulties, things might get harder when you need advanced features, such as mixing landscape and portrait pages within the PDF, using the table of content, or merging many PDFs together.</p><p id="a592">The browser is not supposed to be a PDFs centered tool, it’s just a convenience functionality used to exports some pages quickly at the origin. We are hijacking that user convenient feature into a largely scaled production feature used by a server.</p><p id="7bbd">By doing this we are exposing ourselves to some strange behaviors.</p><p id="1f0b">If you choose to proceed like so, have a look at <a href="https://github.com/alixaxel/chrome-aws-lambda">https://github.com/alixaxel/chrome-aws-lambda</a> which is a library that’s is guaranteed to works in cloud functions whereas pure puppeteer might not…</p><p id="505f"><b>💡 I would recommend this method if you’re running short in time and your use case is simple as it’s really easy to implement.</b></p><h2 id="c814">Using GotenBerg and Docker to generate PDFs</h2><p id="48b7">In the same fashion, you’ve Gotenberg, a Docker-based solution that is presented as an autonomous API server for dealing with PDFs</p><div id="d5b2" class="link-block"> <a href="https://thecodingmachine.github.io/gotenberg/"> <div> <div> <h2>Markdown</h2> <div><h3>Gotenberg is a Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF. HTML and…</h3></div> <div><p>thecodingmachine.github.io</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*AJFcuKniVQ1t8WsN)"></div> </div> </div> </a> </div><p id="e073">It’s a great tool and you should definitely have a look at it!</p><h2 id="a6c6">Using “PDF lib” library</h2><p id="910d">After my research, this is probably the most promising library to deal with PDFs as it supports various panel of use cases with forms, metadata, and overlay.</p><p id="2e36"><b>🎉 Oh and yeah I talk about it here but it’s CROSS-PLATFORM</b></p><p id="b078">Written in TypeScript and compiled to pure JavaScript with no native dependencies. Works in any JavaScript runtime, including browsers, Node, Deno, and even React Native.</p><div id="a451" class="link-block"> <a href="https://pdf-lib.js.org/"> <div> <div> <h2>PDF-LIB · Create and modify PDF documents in any JavaScript environment.</h2> <div><h3>Create and modify PDF documents in any JavaScript environment.</h3></div> <div><p> Create and modify PDF documents in any JavaScript environment.pdf-lib.js.org</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/)"></div> </div> </div> </a> </div><p id="0dae">Using merging we can play with different orientations on one document by merging two different PDFs. You can think of this library as PDFKit but with some additional implementation to avoid using Canva for the first use case.</p><p id="6c7a"><b>⚡️ This is really a great tool and I guess it’s currently the winner in terms of free and open-source solutions it’s also great to note that it’s cross-platform.</b></p><h2 id="9e36">Using third-party service to generate PDFs on NodeJS</h2><p id="c667">And the last one of this article is SAAS, the thing is that SAAS is most of the time expensive as you pay for earning some time in integration.</p><p id="afda">SAAS has also the issue that you have a tight coupling to the external service and you depend on their potentially changing policies and pricing variations.</p><p id="b7fa">But SAAS are generally easy to implement and secured in terms of that their team is working on it and only on it with probably a lot of testing tools. They also provide supports for help if any issue is found.</p><p id="8615">Here are some tools that look promising:</p><ul><li><a href="https://pdfgeneratorapi.com/">https://pdfgeneratorapi.com/</a></li><li><a href="https://docraptor.com/">https://docraptor.com/</a> (Based on HTML but with great features such as mixing layout)</li><li><a href="https://www.docmosis.com/">https://www.docmosis.com/</a></li></ul><p id="66c2">If you can afford any of those, this might be a good solution for you!</p><h1 id="a9a6">Takeaway</h1><p id="7bd1">Think of your need and how far you can make tradeoffs on it. Thinks about essentials questions:</p><ul><li>Does it need to work offline?</li><li>How complex is my PDF file?</li><li>Do I have a backend, is it a server or cloud functions?</li><li>How much time do I have to make that?</li><li>Can I pay for bringing a third party service in the project?</li></ul><p id="a7d7">With that in mind, you can choose whether you’re going server or client-side. Then you can use some techniques like the puppeteer one or make a custom implementation. If you’re rolling on gold, you can even transfer the responsibility on an external service that is going to be responsible for that.</p><p id="53a7"><a href="https://codingspark.io?referral=medium"><b>🇫🇷 If you’re French 🥖 ?</b> Alors je te propose de découvrir ⚡️ <b>Coding Spark</b> et de t’abonner à ma newsletter tech pour recevoir gratuitement du contenu tech!</a></p></article></body>

Experience Feedback

Most Efficient Ways For Building PDFs Files With Backend and Frontend JavaScript

Some observations after I researched building PDFs with JavaScript on Frontend (React) or Backend side (Cloud functions, monoliths, etc), and how to.

Everybody is facing the need of building PDFs somedays in its developer career.

PDF is a very common format made by Adobe, which is optimally vectorial. This means that no matter where you’re using it, on any device all the content will scale properly to be displayed as High Definition content.

Let’s be honest, you have to know that in terms of a feature with today’s tools: building PDFs is probably in my opinion, one of the hardest things to do… Things can get really complicated depending on the need and if you’re not able to make tradeoffs with the customer about things, it gonna be really time-consuming or expensive.

But first, let’s have a big picture: PDFs can be sorted into two kinds :

  • Simple PDF: Those are displaying texts, links, emphasis, and basics assets like images without complex things. Their layout is pretty common. Think of a simple article PDF without complexes things: the one you could have written in markdown then exported to PDF.
  • Complexes PDF: that needs metadata, SSL encryption to prevent writing, charts, sections summary, table of contents, automatic pages number, mixing landscape, and portrait pages. You might also need forms, forms filling, attachment, or even composing PDF with edition, fusion, overlay…

To solve those two need, you have mainly two way of implementing it:

  • Some PDFs are just images based: The whole PDF or some part is a screenshot of some runtime UI. That way if you zoom on it, they will lose quality. It’s a poor trick to deal with PDF, but it works for things like A4 printing as the size if “fixed”. You often see those kinds of PDFs when someone scans a book’s pages to make it available in the numeric world.
  • Whereas best quality PDFs are vector-based, which means you can zoom on it or print it and you’ll end up with a top-grade quality. That’s what a PDF is generally supposed to be.

Where some techniques and libraries offer flexibility and such a good developer experience. They tend to be limited with advanced features such as a table of contents or SSL signing.

⚡️ This article is condensed of my research and observations, it will present many ways to deal with PDFs with pros/cons for each practice. It’s also open for your observations guys, so feel free to reach me on LinkedIn if you have any comments.

Oh and one last thing! You can build PDFs on frontend or backend depending on your need, let’s see that in detail.

Should I build PDFs on the Frontend / Client-side?

Building PDFs on the frontend side is the process of only using the web browser to generate the file (or any kind of frontend client, such as a Mobile Application).

Then the browser will display it or trigger a download of the BLOB (Binary Large Object) without making any network request.

✅ Using frontend PDF generation has various benefits:

  • It saves resources from your server, it’s especially useful when you generate a lot of PDFs for a lot of users and very often.
  • It allows offline capabilities such as with progressive web apps. You can therefore export PDFs from anywhere, even in the airplane and all of this without any internet connection.
  • It’s secure and GDPR compliant because you can use user data without making them flying through the network or even being known by your server.

❌ But it also has this amount of drawbacks:

  • You have less control over access policies as the code lives in the frontend and it might be harder to restrict access to some features, like for a paid plan.
  • You might need code adaptation depending on the platform as not every browser works the same way neither are equals. Sometimes some features might just lack support on some browser.
  • You need a backend and of course, you’ll pay for it every month. Some apps are backend less and it would be sad to have to build and host one just for that use case.

Write PDF in pure JavaScript

First, let’s see the “classic way” using some kind of imperative programming in JavaScript.

For that, you can use something like https://pdfkit.org/ on the frontend (but it also work on the backend, as it’s a polymorphic library, good point!).

Let’s see a quick example of what you can achieve at https://pdfkit.org/demo/out.pdf

The following snippet shows how easy is it to write texts, images, and also SVGs.

// create a document and pipe to a blob
var doc = new PDFDocument();
var stream = doc.pipe(blobStream());
// draw some text
doc.fontSize(25).text('Here is some vector graphics...', 100, 80);
// some vector graphics
doc
  .save()
  .moveTo(100, 150)
  .lineTo(100, 250)
  .lineTo(200, 250)
  .fill('#FF3300');
doc.circle(280, 200, 50).fill('#6600FF');
// an SVG path
doc
  .scale(0.6)
  .translate(470, 130)
  .path('M 250,75 L 323,301 131,161 369,161 177,301 z')
  .fill('red', 'even-odd')
  .restore();
// and some justified text wrapped into columns
doc
  .text('And here is some wrapped text...', 100, 300)
  .font('Times-Roman', 13)
  .moveDown()
  .text(lorem, {
    width: 412,
    align: 'justify',
    indent: 30,
    columns: 2,
    height: 300,
    ellipsis: true
  });
// end and display the document in the iframe to the right
doc.end();
stream.on('finish', function() {
  iframe.src = stream.toBlobURL('application/pdf');
});

Alright! Great! It’s just a matter of sequencing imperative instructions, but that’s all, a kind of low-level API. Do you need custom charts? You’ll need to make your own with SVG and something like d3-js.

As it’s imperative and especially low API it can take some time to achieve the expected final results and it might require a lot of code. You’ll probably need some 2D modelization using the Vectors to draw what you need and the tool won’t help you with that.

If you’re using React JS you can achieve something similar with a declarative wrapper that provides a bit higher tier components.

Using ReactJS

The best tool on the React context is https://react-pdf.org/ it allows you to design PDF using React components and use some kind of CSS language for the layout, which is great.

import React from 'react';
import { Page, Text, View, Document, StyleSheet } from '@react-pdf/renderer';
// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: 'row',
    backgroundColor: '#E4E4E4'
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1
  }
});
// Create Document Component
const MyDocument = () => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
      </View>
    </Page>
  </Document>
);

Alright, this is a bit better and dead simple isn’t it? It’s also easier to maintain as it uses kind of JSX instructions and components which are a great way to split our interface.

But it comes with the same issues. It remains still low tier and also relies on canvas for specifics needs such as charts. Here again, you’ll need some external library.

Under the hood react-pdf uses PDFKit.

For frontend in JavaScript, I guess tools based on PDFKit are the only viable tools but I might have lacked somethings, feel free to reach me if you have a higher level API with better support :)

We’ll see one more on the frontend side a bit further in that article as it’s also a cross-platform tool :)

Or should I build PDFs on Backend / Server with NodeJS or Cloud Function?

In that case, every logic is delegated to the server that will own everything to render our PDF and sent it to the client application.

✅ Using backend PDF generation has various benefits:

  • It gives more capabilities of making PDFs as you can rely on some existing binary from other languages and specialized in PDFs generation.
  • You have more control over everything such as access control policies as it’s server authority, you could just cut off access if the user hasn’t paid for example.
  • You can use a third-party service and control access and usage on it.
  • You can ensure that the results will be the same on all devices, as you control the execution environment. When using backend you generally ensure consistency between client platforms.

❌ But it also has this amount of cons:

  • As the main drawback, you need an internet connection on the frontend.
  • You need a backend that will cost some every month. A backend that you might need to scale depending on frequentation.
  • If the backend fall, the feature falls whereas in frontend integration everything would have still worked.
  • It could also be less secure because you might need to send user information to the backend that he doesn’t already collect for other purposes.

Choosing the proper environment for backend PDFs generation

Before building PDFs on the backend, you must be aware of your environment and shipped library. As an example, you can’t use everything in a cloud function environment because it might lack some binaries.

  • Do I have a Ubuntu Linux, CentOS, or even Windows server?
  • Is my code running on a barebone server or inside of a cloud function?
  • What are my RAM and Processor capabilities?

Here are some questions you should ask yourself. With that in mind, there are various ways of building PDFs on the server-side.

Some about HTML and are very useful for small use cases. Others are about bare-bone PDFs clients, which are way harder but also more efficient for complex use cases.

You can even rely on an external service such as SAAS software.

Using Puppeteer to generate PDFs on the backend side

Puppeteer is supposed to be a headless client for chromium-based browsers, it is made by Google engineers. You are writing code that drives the browser on some pages or inject some HTML into the browser, then you can interact with the HTML document.

Therefore, you’ll use the functionality save to PDF of the browser, that way all you have to do is to design a page with CSS specific for your print or add a CSS print sheet.

We end up with a code like this:

const chromium = require('chrome-aws-lambda');
exports.handler = async (req, res) => {
  let result = null;
  let browser = null;
try {
    browser = await chromium.puppeteer.launch({
      args: chromium.args,
      defaultViewport: chromium.defaultViewport,
      executablePath: await chromium.executablePath,
      headless: chromium.headless,
      ignoreHTTPSErrors: true,
    });
let page = await browser.newPage();
await page.goto('https://example.com');
const pdfBuffer = await page.pdf({ printBackground: true });
res.set("Content-Type", "application/pdf");
  res.set("Content-Disposition", 'attachment; filename="My-report.pdf"');
  res.status(200).send(pdfBuffer);
  } catch (error) {
    return res.status(500).send(error);
  } finally {
    if (browser !== null) {
      await browser.close();
    }
  }
};

This is great, but let’s be honest kind of hacky.

Speaking of difficulties, things might get harder when you need advanced features, such as mixing landscape and portrait pages within the PDF, using the table of content, or merging many PDFs together.

The browser is not supposed to be a PDFs centered tool, it’s just a convenience functionality used to exports some pages quickly at the origin. We are hijacking that user convenient feature into a largely scaled production feature used by a server.

By doing this we are exposing ourselves to some strange behaviors.

If you choose to proceed like so, have a look at https://github.com/alixaxel/chrome-aws-lambda which is a library that’s is guaranteed to works in cloud functions whereas pure puppeteer might not…

💡 I would recommend this method if you’re running short in time and your use case is simple as it’s really easy to implement.

Using GotenBerg and Docker to generate PDFs

In the same fashion, you’ve Gotenberg, a Docker-based solution that is presented as an autonomous API server for dealing with PDFs

It’s a great tool and you should definitely have a look at it!

Using “PDF lib” library

After my research, this is probably the most promising library to deal with PDFs as it supports various panel of use cases with forms, metadata, and overlay.

🎉 Oh and yeah I talk about it here but it’s CROSS-PLATFORM

Written in TypeScript and compiled to pure JavaScript with no native dependencies. Works in any JavaScript runtime, including browsers, Node, Deno, and even React Native.

Using merging we can play with different orientations on one document by merging two different PDFs. You can think of this library as PDFKit but with some additional implementation to avoid using Canva for the first use case.

⚡️ This is really a great tool and I guess it’s currently the winner in terms of free and open-source solutions it’s also great to note that it’s cross-platform.

Using third-party service to generate PDFs on NodeJS

And the last one of this article is SAAS, the thing is that SAAS is most of the time expensive as you pay for earning some time in integration.

SAAS has also the issue that you have a tight coupling to the external service and you depend on their potentially changing policies and pricing variations.

But SAAS are generally easy to implement and secured in terms of that their team is working on it and only on it with probably a lot of testing tools. They also provide supports for help if any issue is found.

Here are some tools that look promising:

If you can afford any of those, this might be a good solution for you!

Takeaway

Think of your need and how far you can make tradeoffs on it. Thinks about essentials questions:

  • Does it need to work offline?
  • How complex is my PDF file?
  • Do I have a backend, is it a server or cloud functions?
  • How much time do I have to make that?
  • Can I pay for bringing a third party service in the project?

With that in mind, you can choose whether you’re going server or client-side. Then you can use some techniques like the puppeteer one or make a custom implementation. If you’re rolling on gold, you can even transfer the responsibility on an external service that is going to be responsible for that.

🇫🇷 If you’re French 🥖 ? Alors je te propose de découvrir ⚡️ Coding Spark et de t’abonner à ma newsletter tech pour recevoir gratuitement du contenu tech!

JavaScript
React
Nodejs
Software Development
Web Development
Recommended from ReadMedium