Skip to content

Frequently Asked Questions

Wojciech Maj edited this page May 22, 2024 · 9 revisions

When I'm trying to load a PDF file from an external source, I'm given a message "Failed to load PDF file.".

Most common cause of this issue is a network problem of some kind. Check if the URL you're loading the PDF file from is correct.

If you are sure the URL to the external source you're trying to load is correct, most likely you are experiencing effects of Same-origin Policy. In order to load files from domains other than your own you can do the following:

  • Ask domain owner to include your domain in Access-Control-Allow-Origin HTTP header.
  • Use a server-side proxy that will go around Same-origin policy limitations (beware: that is a potential security issue, so be sure you know what you're doing before creating one).

Read more about CORS.

I render Document, but nothing is rendered. Why?

If you are using React-PDF like this:

<Document file="http://example.com/document.pdf" />

then nothing will be rendered. Document component only gives its children (and grandchildren, and great-grandchildren…) a "context" on PDF file you're trying to render. React-PDF can do multiple things with PDF file. You can, for example:

  • Render a page
  • Render a few pages
  • Render document's outline (Table of Contents)

so you need to specify what would you like to do. So to render a page, you need to write:

<Document file="http://example.com/document.pdf">
  <Page pageNumber={1} />
</Document>

React-PDF reloads itself with every render or fetches a file twice. What's going on?

If you are using React-PDF like this:

<Document file={{ url: 'http://example.com/document.pdf' }} />

then React-PDF thinks you're giving it new (referentially unequal) file object with every render. Try it in your browser's console!

> ({ url: 'http://example.com/document.pdf' }) === ({ url: 'http://example.com/document.pdf' })
< false // surprise!

To deal with this, file object must be memoized by setting it in component's state, useMemo or other similar technique.

const file = useMemo(() => ({ url }), [url]);

return (
  <Document file={file} />
);

This way React-PDF will get the same object with each render.

Note: This also applies to options prop.

Layers of my PDF are misaligned, e.g. the text selection doesn't match actual position of the text. What can I do?

PDF consists of several layers:

  • Canvas
  • Text layer
  • Annotation layer

These layers must be aligned in order for the PDF to look and work well. It can be tempting to auto-resize <canvas> using CSS - but don't do this! By doing so, you only resize one layer, while leaving the others intact. React-PDF must know the exact size you want to render the document in. Provide scale, width, or height props as desired, and use ResizeObserver or Window resize event to maintain responsiveness.

How do I load a PDF from Base64?

To open load a PDF from Base64, you need to need to transform it to Data URL. Don't worry, it's easy!

Here's a sample PDF file in Base64:

JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyA5IFRmKFRlc3QpJyBFVAplbmRzdHJlYW0KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCA1IDAgUgovQ29udGVudHMgOSAwIFIKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0tpZHMgWzQgMCBSIF0KL0NvdW50IDEKL1R5cGUgL1BhZ2VzCi9NZWRpYUJveCBbIDAgMCA5OSA5IF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4+CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4+CiUlRU9G

all you have to do is prepend your Base64 string with data:application/pdf;base64,. It turns into a valid link. Try and paste the string below into your browser!

data:application/pdf;base64,JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyA5IFRmKFRlc3QpJyBFVAplbmRzdHJlYW0KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCA1IDAgUgovQ29udGVudHMgOSAwIFIKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0tpZHMgWzQgMCBSIF0KL0NvdW50IDEKL1R5cGUgL1BhZ2VzCi9NZWRpYUJveCBbIDAgMCA5OSA5IF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4+CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4+CiUlRU9G

So, how to do this with React-PDF? Like so:

<Document file={`data:application/pdf;base64,${base64String}`}>
  <Page pageNumber={1} />
</Document>

Rendering PDF is too slow. What can I do?

Ensure the server you're serving PDFs from supports Partial Content

React-PDF is capable of downloading partial content, meaning, if have a PDF with a book, but only render its cover, it's smart enough not to download the entire book - provided that PDF is built correctly and the server supports Partial Content.

Ensure you're rendering only what you need

Rendering multiple pages at once is a compute intensive task and WILL be slow, even on good machines. Use virtualization to only render the pages the user sees.

Consider capping the maximum pixel density

By default, React-PDF renders PDFs at native pixel density. The higher the pixel density, the more actual pixels need to be rendered on the screen. Modern devices, especially mobile, have higher pixel density.

For example, iPhone has pixel density of 3. Each "1x1px" square is going to be rendered by 9 physical pixels on the screen. So, a typical A4 page (794x1123px), will actually be rendered as 2382x3369px canvas. That's a lot of work, especially for a mobile phone!

You could cap maximum pixel density by passing e.g. Math.min(2, window.devicePixelRatio) to devicePixelRatio prop, preventing obscenely high pixel density, while maintaining good looks on most devices.

Bundling my app with React-PDF is too slow. What can I do?

Some performance decrease after React-PDF is added to your bundle is inevitable. React-PDF uses Mozilla's PDF.js which weighs around 2 MB before compression.

Here are several things you can do to improve this.

Ensure you're using the most up to date version of Node.js and bundler

Newest versions of Node.js can significantly improve performance of bundlers like Webpack. It works the other way around, too: bundlers like Webpack take advantage of some tricks Node.js can do in the newest versions. It's a good idea to keep them both up to date.

Make use of multi-process minifying in UglifyJsPlugin

With parallel option in UglifyJsPlugin, you can use multiple processor cores to do the minifying. This speeds up bundling process by quite a bit.

new webpack.optimize.UglifyJsPlugin({
+  parallel: true,
}),

Enable cache in UglifyJsPlugin

PDF.js files remain unchanged between builds, so it won't hurt to use caching to prevent UglifyJsPlugin from doing the same job over and over again. This speeds the second and all the next builds.

new webpack.optimize.UglifyJsPlugin({
+  cache: true,
}),