@react-pdf/renderer vs pdf-lib vs pdfjs-dist vs react-pdf vs react-pdf-html
Generating and Displaying PDFs in React Applications
@react-pdf/rendererpdf-libpdfjs-distreact-pdfreact-pdf-htmlSimilar Packages:

Generating and Displaying PDFs in React Applications

These libraries solve different parts of the PDF workflow. @react-pdf/renderer and react-pdf-html focus on creating new PDFs using React components. pdf-lib handles low-level editing and merging of existing files. react-pdf and pdfjs-dist are designed for viewing PDFs in the browser. Choosing the right tool depends on whether you need to generate, edit, or display documents.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
@react-pdf/renderer016,597292 kB409a month agoMIT
pdf-lib08,478-3155 years agoMIT
pdfjs-dist053,37335.3 MB452a month agoApache-2.0
react-pdf011,074309 kB203 months agoMIT
react-pdf-html0214361 kB415 months agoMIT

Generating and Displaying PDFs in React Applications

The JavaScript ecosystem offers several tools for working with PDFs, but they serve very different purposes. Some libraries create new documents from scratch, others modify existing files, and some are built strictly for viewing. Mixing them up can lead to major architectural issues. Let's break down how @react-pdf/renderer, pdf-lib, pdfjs-dist, react-pdf, and react-pdf-html handle common tasks.

🎯 Primary Goal: Creation vs. Viewing vs. Editing

The first decision is whether you need to make a PDF, show a PDF, or change a PDF. These packages do not overlap much here.

@react-pdf/renderer creates new PDFs using React components.

  • You define the layout using custom primitives like <View> and <Text>.
  • Ideal for dynamic reports, invoices, or certificates.
// @react-pdf/renderer: Create a new document
import { Document, Page, Text } from '@react-pdf/renderer';

const MyDoc = () => (
  <Document>
    <Page>
      <Text>Hello World</Text>
    </Page>
  </Document>
);

react-pdf-html also creates new PDFs but allows standard HTML tags.

  • You write <div> and <p> instead of custom components.
  • Best for teams that want to reuse existing CSS knowledge.
// react-pdf-html: Create with HTML syntax
import { HTML } from 'react-pdf-html';

const MyDoc = () => (
  <HTML>
    <div>
      <p>Hello World</p>
    </div>
  </HTML>
);

pdf-lib modifies or creates PDFs using a low-level API.

  • You draw text and shapes imperatively.
  • Great for merging files or filling forms programmatically.
// pdf-lib: Modify or create low-level
import { PDFDocument } from 'pdf-lib';

const doc = await PDFDocument.create();
const page = doc.addPage();
page.drawText('Hello World');

react-pdf displays existing PDFs in the browser.

  • You cannot create content with this library.
  • It renders pages from a file URL or blob.
// react-pdf: Display an existing file
import { Document, Page } from 'react-pdf';

function Viewer() {
  return <Document file="/invoice.pdf"><Page pageNumber={1} /></Document>;
}

pdfjs-dist provides the engine for displaying PDFs.

  • It is the core library behind react-pdf.
  • Requires manual setup for rendering to canvas.
// pdfjs-dist: Low-level viewing
import * as pdfjsLib from 'pdfjs-dist';

const loadingTask = pdfjsLib.getDocument('/invoice.pdf');
const pdf = await loadingTask.promise;
const page = await pdf.getPage(1);

πŸ“ Syntax: React Components vs. Imperative API vs. HTML

How you define content varies wildly between these tools. This affects developer speed and learning curve.

@react-pdf/renderer uses a subset of CSS flexbox.

  • Styles are passed as objects to components.
  • Familiar to React developers but requires learning specific primitives.
// @react-pdf/renderer: Styling
const styles = StyleSheet.create({
  page: { padding: 30 },
  text: { fontSize: 12 }
});

<Text style={styles.text}>Content</Text>

react-pdf-html uses standard CSS classes.

  • You can write normal class names and style sheets.
  • Reduces the need to learn a new styling system.
// react-pdf-html: Standard CSS
<div className="container">
  <p className="text">Content</p>
</div>

// CSS: .container { padding: 30px; }

pdf-lib uses imperative drawing commands.

  • You specify coordinates for every element.
  • High control but verbose for complex layouts.
// pdf-lib: Imperative drawing
page.drawText('Content', {
  x: 50,
  y: 500,
  size: 12
});

react-pdf does not define content syntax.

  • It focuses on viewer props like scale and rotation.
  • You configure how the file is shown, not what is inside.
// react-pdf: Viewer configuration
<Document file="/file.pdf">
  <Page pageNumber={1} scale={1.5} />
</Document>

pdfjs-dist requires manual canvas rendering.

  • You must get the viewport and draw to a context.
  • Gives full control over how pixels are painted.
// pdfjs-dist: Canvas rendering
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
await page.render({ canvasContext: ctx, viewport }).promise;

πŸ”„ Working with Existing Files

Sometimes you need to edit a file someone else made. This is where creation tools fail and editing tools shine.

@react-pdf/renderer cannot edit existing PDFs.

  • It only generates new binary data from components.
  • Trying to import a PDF here will not work.
// @react-pdf/renderer: Not supported
// Cannot load an existing PDF to modify it
// Must recreate the document from scratch

react-pdf-html cannot edit existing PDFs.

  • Like the renderer, it builds new files from HTML.
  • Use this only for generating new content.
// react-pdf-html: Not supported
// Cannot load an existing PDF to modify it
// Must recreate the document from scratch

pdf-lib excels at modifying existing files.

  • You can load a buffer, add text, and save.
  • Supports merging, splitting, and form filling.
// pdf-lib: Load and modify
const existingPdfBytes = await fetch('/form.pdf').then(res => res.arrayBuffer());
const doc = await PDFDocument.load(existingPdfBytes);
const form = doc.getForm();
form.getTextField('name').setText('John Doe');

react-pdf loads existing files for viewing only.

  • You cannot change the content inside the file.
  • It simply renders the bytes to the screen.
// react-pdf: Load for viewing
<Document file="/existing-form.pdf">
  <Page pageNumber={1} />
</Document>

pdfjs-dist loads existing files for viewing only.

  • It parses the binary structure for rendering.
  • Does not provide methods to save changes.
// pdfjs-dist: Load for viewing
const loadingTask = pdfjsLib.getDocument('/existing-form.pdf');
const pdf = await loadingTask.promise;
// No save method available

🌐 Environment Support: Node.js vs. Browser

Where your code runs matters. Some libraries work everywhere, while others are tied to the DOM.

@react-pdf/renderer works in Node.js and Browser.

  • You can generate PDFs on the server during SSR.
  • Also works in client-side React apps.
// @react-pdf/renderer: Server or Client
// Works in Next.js API routes or browser components
const blob = await pdf(<MyDoc />).toBlob();

react-pdf-html works in Node.js and Browser.

  • Inherits environment support from the renderer.
  • Ensure your HTML/CSS features are supported in both.
// react-pdf-html: Server or Client
// Works similarly to renderer
const blob = await pdf(<MyDoc />).toBlob();

pdf-lib works in Node.js and Browser.

  • Very flexible for backend scripts or frontend tools.
  • Does not rely on the DOM for core logic.
// pdf-lib: Universal
// Runs in Node.js scripts or browser bundles
const pdfBytes = await doc.save();

react-pdf is designed for the Browser.

  • It relies on DOM elements for rendering pages.
  • Server-side rendering requires special configuration.
// react-pdf: Browser focused
// Needs window/document for canvas rendering
// SSR requires disabling canvas rendering

pdfjs-dist works in Node.js and Browser.

  • Core engine is environment agnostic.
  • Rendering to canvas requires a DOM in the browser.
// pdfjs-dist: Universal core
// Can parse PDFs in Node, render in Browser
pdfjsLib.GlobalWorkerOptions.workerSrc = '...';

πŸ“Š Summary Table

PackagePrimary UseSyntax StyleEdit Existing?Environment
@react-pdf/rendererCreate NewReact Components❌Node & Browser
react-pdf-htmlCreate NewHTML/CSS❌Node & Browser
pdf-libEdit/MergeImperative APIβœ…Node & Browser
react-pdfView OnlyReact Components❌Browser
pdfjs-distView OnlyLow-Level API❌Node & Browser

πŸ’‘ Final Recommendation

Pick the tool that matches your goal.

For Creating Documents: Use @react-pdf/renderer for most React projects. It is stable and well-supported. Use react-pdf-html only if you need standard HTML CSS support and accept the risk of community maintenance.

For Editing Documents: Use pdf-lib. It is the only choice here for merging, splitting, or filling forms programmatically.

For Viewing Documents: Use react-pdf. It saves you from setting up pdfjs-dist manually. Only drop down to pdfjs-dist if you need a highly custom viewer interface.

Final Thought: These libraries do not compete β€” they complement each other. A common pattern is using @react-pdf/renderer to generate a report, pdf-lib to stamp it with a signature, and react-pdf to let the user download or view it.

How to Choose: @react-pdf/renderer vs pdf-lib vs pdfjs-dist vs react-pdf vs react-pdf-html

  • @react-pdf/renderer:

    Choose @react-pdf/renderer if you need to generate dynamic PDFs like invoices or reports using React components. It offers a stable API with CSS-like styling and works in both Node.js and the browser. This is the standard choice for creation tasks in the React ecosystem.

  • pdf-lib:

    Choose pdf-lib if you need to modify existing PDFs, such as filling forms, merging documents, or adding watermarks. It provides low-level control and works in Node.js and the browser. It is not designed for creating complex layouts from scratch using React components.

  • pdfjs-dist:

    Choose pdfjs-dist if you need to build a custom PDF viewer from scratch. It provides low-level access to rendering PDF pages to canvas. This requires more setup than wrapper libraries but offers maximum control over the viewing experience.

  • react-pdf:

    Choose react-pdf if you want to display PDFs in a React app without building a viewer from scratch. It wraps pdfjs-dist with easy-to-use components like <Document> and <Page>. This is the fastest way to add PDF viewing to a React project.

  • react-pdf-html:

    Choose react-pdf-html if you want to generate PDFs using standard HTML and CSS syntax instead of custom components. Be aware that this relies on community maintenance and may lag behind @react-pdf/renderer updates. It is best for simple documents where HTML fidelity is key.

README for @react-pdf/renderer

React renderer for creating PDF files on the browser and server

How to install

yarn add @react-pdf/renderer

How it works

import React from 'react';
import { Document, Page, Text, View, 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>
);

Web. Render in DOM

import React from 'react';
import ReactDOM from 'react-dom';
import { PDFViewer } from '@react-pdf/renderer';

const App = () => (
  <PDFViewer>
    <MyDocument />
  </PDFViewer>
);

ReactDOM.render(<App />, document.getElementById('root'));

Node. Save in a file

import React from 'react';
import ReactPDF from '@react-pdf/renderer';

ReactPDF.render(<MyDocument />, `${__dirname}/example.pdf`);

Contributors

This project exists thanks to all the people who contribute. Looking to contribute? Please check our [contribute] document for more details about how to setup a development environment and submitting code.

Sponsors

Thank you to all our sponsors! [Become a sponsors]

Backers

Thank you to all our backers! [Become a backer]

License

MIT Β© Diego Muracciole