wojtekmaj / react-pdf

Display PDFs in your React app as easily as if they were images.

Home Page:https://projects.wojtekmaj.pl/react-pdf

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Render breaks in nextjs 14.1.0 - ReferenceError: Can't find variable: exports leads to "Failed to load PDF file."

ptpittman opened this issue · comments

Before you start - checklist

  • I followed instructions in documentation written for my React-PDF version
  • I have checked if this bug is not already reported
  • I have checked if an issue is not listed in Known issues
  • If I have a problem with PDF rendering, I checked if my PDF renders properly in PDF.js demo

Description

I have a site using nextjs app dir, rendering PDFs in a client component. Was working fine up to 14.0.3. Upgrading to 14.1.0, it now throws an error on client side and cannot load the PDF.

Minimally, my components loads the following outside of the component:

import { pdfjs } from "react-pdf";

import { Document, Page } from "react-pdf";
import "react-pdf/dist/Page/AnnotationLayer.css";

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.js",
  import.meta.url
).toString();

As recommended in docs. I tried moving the pdfjs.GlobalWorkerOptions line into a useEffect to fire on load but this only delayed the error slightly.

I build and deploy using pnpm. I noted the instruction in the docs to add a .npmrc with "public-hoist-pattern[]=pdfjs-dist", which I hadn't previously had or apparently needed, but this doesn't resolve the issue.

Steps to reproduce

No public reproduction as I had to revert. Can deploy a test repo if needed.

Expected behavior

PDF displays first page

Actual behavior

Page displays "Failed to load PDF file", browser console

Additional information

Console errors are as follows:

[Error] ReferenceError: Can't find variable: exports (pdf.worker.min.db5d8e2a.js, line 22)
[Error] ReferenceError: Can't find variable: exports
	Global Code (pdf.worker.min.db5d8e2a.js:22)
[Error] Warning: Error: Setting up fake worker failed: "undefined is not an object (evaluating 'window.pdfjsWorker.WorkerMessageHandler')".
	(anonymous function) (app-index.js:35)
	(anonymous function) (hydration-error-info.js:41)
	printWarning (warning.js:26)
	warning (warning.js:45)
	onLoadError (Document.js:315)
	(anonymous function) (Document.js:372)
	commitHookEffectListMount (react-dom.development.js:18071)
	commitHookPassiveMountEffects (react-dom.development.js:19742)
	commitPassiveMountOnFiber (react-dom.development.js:19826)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19889)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19918)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)
	commitPassiveMountOnFiber (react-dom.development.js:19824)
	recursivelyTraversePassiveMountEffects (react-dom.development.js:19808)

Environment

  • Browser (if applicable): All browsers
  • React-PDF version: 7.7.0
  • React version: 18.2.0
  • Webpack version (if applicable): Nextjs Default
  • Next.js: 14.1.0

If the package worked before and stopped working without any changes on our side, it's a Next.js regression and should be reported to them.

I'm not surprised this happened, they notoriously break packages because of the amount of hacks they ship to production.

No doubt - they're playing around a lot with barrel import optimization at the moment and Material UI was broken entirely for 14.0.4. But to help me take this up with them, I do see various tickets throughout history related to pdfjs's lack of a default export sometimes causing problems. Looking at the code these days, it doesn't seem to be the case – is there anything I should look more closely at? (My import method above is correct, right?)

I'm curious how #1690 would perform now that PDF.js is ESM first. Unfortunately we're not ready for a pre-release even, let alone full release.

i was facing the same issue as well in nextjs 14.1.0. Changing the import worker to external cdn fixes it for me

pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;

"react-pdf": "^7.7.0",
"next": "^14.1.0",

Nice! Good workaround for now. Definitely points to their webpack optimizations continuing to do new wild and unplanned things.

instead of CDN, I use local assets instead

// package.json
{
  "script": {
    "postinstall": "node ./postinstall.js"
  }
}
// postinstall.js
const path = require('path');
const fs = require('fs');

const pdfjsDistPath = path.dirname(require.resolve('pdfjs-dist/package.json'));
const pdfWorker = path.join(pdfjsDistPath, 'build', 'pdf.worker.min.js');

fs.copyFileSync(pdfWorker, './public/js/pdf.worker.min.js');
// PDFViewer.tsx
'use client';

import { Document, Page, pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.js';

instead of CDN, I use local assets instead

// package.json
{
  "script": {
    "postinstall": "node ./postinstall.js"
  }
}
// postinstall.js
const path = require('path');
const fs = require('fs');

const pdfjsDistPath = path.dirname(require.resolve('pdfjs-dist/package.json'));
const pdfWorker = path.join(pdfjsDistPath, 'build', 'pdf.worker.min.js');

fs.copyFileSync(pdfWorker, './public/js/pdf.worker.min.js');
// PDFViewer.tsx
'use client';

import { Document, Page, pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.js';

I used a slightly modified version and resolved the issue for me (with bun)

{
  "script": {
    "postinstall": "bun ./scripts/postinstall.mjs"
  }
}
// scripts/postinstall.mjs
import fs from "node:fs";
import path from "node:path";

const pdfjsDistPath = path.dirname(
    path.resolve("node_modules/pdfjs-dist/package.json")
);
const pdfjsWorkerPath = path.join(pdfjsDistPath, "build", "pdf.worker.min.js");

fs.copyFileSync(pdfjsWorkerPath, "public/pdf.worker.min.js");
"use client";

pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.js";