next.js: Import pdfjs-dist not working correctly

Link to the code that reproduces this issue

https://github.com/Luluno01/pdfjs-dist-import-reproducer

To Reproduce

  1. Start the application in development mode (next dev)
  2. Open home page (/)
  3. Got an error in dev server console “Attempted import error: ‘getDocument’ is not exported from ‘pdfjs-dist’ (imported as ‘pdfjs’).” and getDocument being undefined.

Current vs. Expected behavior

The ESM package pdfjs-dist should be imported correctly. The actual outcome, however, is nothing will be imported – all exported objects are undefined, including the default export.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
Binaries:
  Node: 21.1.0
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.0.3-canary.1
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router, TypeScript (plugin, built-in types)

Additional context

Same problem with version “13.5.4” and version “13.0.0”.

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Reactions: 4
  • Comments: 54 (3 by maintainers)

Most upvoted comments

Hi, there’re some bundling fixes are landed on the canary (14.0.5-canary.45) I tested against latest canary it works well now. getDocument is a valid function. Another thing to notice that you don’t need to remove .default to get the full module imports await import('pdfjs-dist')

my use case is for a file image generator in a hook

` import pdfjs from “pdfjs-dist”;

export default function useFileImageGenerator() {

function getThumbnail(file: File) { const canvas = document.createElement(“canvas”); const context = canvas.getContext(“2d”);

console.log("1", file, canvas, context);

if (context !== null) {
  pdfjs
    .getDocument(file)
    .promise.then(pdfDoc => pdfDoc.getPage(1))
    .then(page => {
      console.log("2", page);
      const viewport = page.getViewport({ scale: 1 });
      canvas.width = viewport.width;
      canvas.height = viewport.height;

      const renderContext = {
        canvasContext: context,
        viewport: viewport,
      };
      console.log("3", renderContext);
      return page.render(renderContext).promise;
    })
    .then(() => {
      const imageDataUrl = canvas.toDataURL("image/png");

      console.log("4", imageDataUrl);
      const blob = dataURLtoBlob(imageDataUrl);
      // Create a File object
      const fileName = `${file.name}_screenshot.png`;

      const thumbnailImage = new File([blob], fileName, { type: "image/png" });
      console.log("5", thumbnailImage);
      return thumbnailImage;
    })
    .catch(error => {
      console.error("unable to convert pdf to image:", error);
    });
}

}

const dataURLtoBlob = (dataURL: string) => { const arr = dataURL.split(“,”); const mimeMatch = arr[0].match(/😦.*?);/); const mime = mimeMatch ? mimeMatch[1] : “application/octet-stream”; const bstr = window.atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n);

while (n--) {
  u8arr[n] = bstr.charCodeAt(n);
}

return new Blob([u8arr], { type: mime });

};

return getThumbnail; } `

next 14.0.5 pdfjs-dist ^3.11.174 canvas 2.11.2

image

@huozhi Any thoughts?

There’re few module resolution related bundling fixes applied after 14.0.4, on canary now. Unfortunately we’re not going to apply them back to 13.x.

Okayyyy… Thank you for your reply. Sounds like I have to upgrade to 14.0.5+ later to be able to use pdfjs with less workaround.

I decided to follow a simple path, I downloaded the stable version from the official website. I put all the files in the public folder. Then I added this tag to my component:

<script src="/pdfjs/pdf.mjs" type="module" />

then adding code in useEffect:

  const pdfjs = window.pdfjsLib as typeof import('pdfjs-dist/types/src/pdf')
  const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.min.mjs');
  pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

  const pdfDocument = pdfjs.getDocument('http://localhost:3000/pdf-files/myFile.pdf')

  console.log('pdfDocument', pdfDocument);

I think it’s also important to clarify that pdfjs-dist could be used in BOTH React and any API routes, not sure if that causes any difference in behavior.

Yes, you are right. And my use case is server-side PDF file processing.

Try importing like this:

import * as PDFJS from 'pdfjs-dist/build/pdf.min.mjs'

I even added https://github.com/mozilla/pdfjs-dist manually into my project, same error, something to do with the imports for sure

Found this. Not a big fan of webpack but I tried to follow the settings in the example provided. Still no luck.

I created a brand new node project and everything works, so this is an issue with how next.js/webpack bundle the different modules.

Interesting thing is I think everything works in the pages router

You mean so far it ONLY works in pages router?