Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-pdf is not working when build with nextjs #136

Closed
nyamba opened this issue Jan 23, 2018 · 38 comments
Closed

react-pdf is not working when build with nextjs #136

nyamba opened this issue Jan 23, 2018 · 38 comments
Assignees
Labels
help wanted Extra attention is needed question Further information is requested stale

Comments

@nyamba
Copy link

nyamba commented Jan 23, 2018

It's working fine on development mode with nextjs. However when I build my nextjs app, it gives me an error that worker.js is not found(404). It looks that *.worker.js is existed in .next director.
next bundle
Can you point me to a way to resolve it.

Thanks for your time.

404 not found

@nyamba nyamba changed the title nexjs building with react-pdf is not working react-pdf is not working when build with nextjs Jan 23, 2018
@wojtekmaj
Copy link
Owner

Hello @nyamba,
I'm not actively supporting nextjs as I don't have all the necessary knowledge. I can only give you one hint:

You can manually set workerSrc path to whatever path you like, so if you define where the worker file should be copied to (hint 2: it does not need building, it can be safely just copied from pdfjs-dist node_module) and how it's called, then your problem is solved entirely.

You could also do the opposite thing, meaning - looking where React-PDF looks for worker file and ensure your bundling process puts it there. But the first option is a safer bet :)

@wojtekmaj wojtekmaj self-assigned this Jan 23, 2018
@wojtekmaj wojtekmaj added the question Further information is requested label Jan 23, 2018
@felizuno
Copy link

FYI for others using Next.js they have a helper that we used to work around this issue.

Our problem was that rendering anything which depends on PDF.js server-side will throw errors, as the library itself contains browser API calls which are not safe in Node. By using the above helper to import the component that handles PDF rendering we were able to defer parsing of the library code to the browser, where it ran without error:

// This is our wrapper component which contains the PDF viewer
const PDFViewer = dynamic(import('../../components/PDFViewer'), { ssr: false });

class ExampleClass extends Component {
  render() {
    return (
      <div>
        <PDFViewer />
      </div>
    );
  }
}

@arnaud-brun
Copy link

arnaud-brun commented Dec 28, 2018

I was facing this problem for a long time in a nextJs production environment: __next[hash].worker.js not found on custom server.

Both provided solutions with custom setOptions method or dynamic import didn't work for me.
So I dedided to work without worker.

/* next.config.js : webpack extension */
 webpack: (config) => {

 /* PdfViewer : override defaults aliases */

 config.resolve.alias = Object.assign({}, config.resolve.alias, {
   "react-pdf": "react-pdf/dist/entry.noworker.js"
 });

 return config;
}

I don't know if it's recommended, but it now works in production.

@wojtekmaj
Copy link
Owner

I see nothing wrong with this code, apart from the fact it won't work with React-PDF 4.x, since there's no longer an option to run React-PDF without a Worker. All browsers should be capable of running the worker though, so you should aim to enable it if possible.

@johnking
Copy link

I am also using next.js and have the same issue, I tried many suggestions and workarounds but failed.

I ended up using this module without worker.

@wojtekmaj wojtekmaj added the help wanted Extra attention is needed label Apr 24, 2019
@wojtekmaj wojtekmaj reopened this Apr 24, 2019
@feluxe
Copy link

feluxe commented Dec 6, 2019

I cannot reproduce the issue with:

    "next": "9.1.4",
    "react": "16.12.0",

This works just fine for me:

import React from "react";
import { Document, Page } from "react-pdf";


class Test extends React.Component {
  render() {
    return (
      <Document
        file={{
          url: "./my.pdf"
        }}
        onLoadError={e =>
          console.log("Error while loading document! " + e.message)
        }
        onSourceError={e =>
          console.log("Error while loading document! " + e.message)
        }
      >
        <Page pageNumber={1} />
      </Document>
    );
  }
}

const index = () => {
  return (
    <div>
      <Test></Test>
    </div>
  );
};

export default index;

@drizco
Copy link

drizco commented Dec 11, 2019

@feluxe

the issue happens when trying to use the service worker implementation, which is supposed to be imported like this: import { Document } from 'react-pdf/dist/esm/entry.webpack';

somewhat related... @wojtekmaj , I'm not seeing the esm or umd directories. I'm using version 4.1.0. I tried importing from react-pdf/dist/entry.webpack, which does exist. I'm getting the error about not finding __next/[hash].worker.js so I'm going to try using version 3.x and the entry.noworker.js file

@wojtekmaj
Copy link
Owner

@RyanDriscoll You're looking at docs for the newer version of React-PDF than you're currently using. Read the docs for 4.1.0 here: https://github.com/wojtekmaj/react-pdf/tree/v4.1.0

@clodal
Copy link

clodal commented May 15, 2020

Have tried this on Next v9 stack and React-PDF v4.1 alongside @felizuno's Dynamic Import patch.

import { Document, Page } from 'react-pdf/dist/entry.webpack'

However, the PDF gets stuck in loading forever. How to get the webpack working with NextJS?

Have also tried to install Next Workers to no avail. (Still loading)

@wojtekmaj
Copy link
Owner

@wojtekmaj , I'm not seeing the esm or umd directories. I'm using version 4.1.0.

You're looking at React-PDF 5.0 docs.

@rajbir123

This comment has been minimized.

@redgumnfp
Copy link

In case anyone comes here looking for NextJs implementation...I got it to work just fine with the below (an amalgamation of all the comments above; thanks all):

Install as per documentation:
npm install react-pdf

NB: ensure you don't already have pdfjs-dist installed, as the version you installed may mismatch this package.

Create a wrapped component, as per documentation:

import React from 'react';

import {
  Document, Page,
} from 'react-pdf/dist/esm/entry.webpack';

const PdfViewer = ({
  url, width, pageNumber
}) => (
  <Document file={url}>
    <Page
      pageNumber={pageNumber}
      width={width}
    />
  </Document>
);

export default PdfViewer;

Import dynamically, as SSR FALSE:

import React from 'react';

import dynamic from 'next/dynamic';

const PdfViewer = dynamic(
  () => import('./PdfViewer'),
  { ssr: false }
);

This will ensure that the correct version of pdf.js is pulled in from this react-pdf package, and Next/webpack does the rest.

@zhzhang
Copy link

zhzhang commented Feb 15, 2021

@redgumnfp this is no longer working, error returned is

./node_modules/react-pdf/dist/esm/pdf.worker.entry.js (./node_modules/worker-loader/dist/cjs.js!./node_modules/react-pdf/dist/esm/pdf.worker.entry.js)
TypeError: Cannot read property 'tapAsync' of undefined

Resulting from a recent-ish change in webpack.
Repro with code here: https://github.com/zhzhang/next-react-pdf-broken

Pulling from the CDN seems to work however.

// PDFViewer.jsx
import { Document, Page } from "react-pdf";
import { pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;

const PdfViewer = ({ file, width, pageNumber }) => (
  <Document file={file}>
    <Page pageNumber={pageNumber} width={width} />
  </Document>
);

export default PdfViewer;

@jeetiss
Copy link
Contributor

jeetiss commented Apr 1, 2021

I have created a minimal next-js + react-pdf codesandbox and everything works fine with current version, look

https://codesandbox.io/s/react-pdf-next-js-y4ev2

@paescuj
Copy link
Contributor

paescuj commented Apr 2, 2021

@jeetiss Thanks! Actually, I think you don't even need to import it dynamically when using it this way.

@jeetiss
Copy link
Contributor

jeetiss commented Apr 3, 2021

I think you don't even need to import it dynamically when using it this way.

@paescuj yes you right! react-pdf works fine with webpack 5, but it still is "future" feature, so I keep dynamic import

with webpack 4 react-pdf throws some warnings about window and file access

@adderpositive
Copy link

adderpositive commented Apr 13, 2021

Hey guys,
for me helped to define JS worker _app.js from CDN.

import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

marekmitko added a commit to marekmitko/e-faktury-next-app-v0-01 that referenced this issue May 22, 2021
@nathansearles
Copy link

import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

@adderpositive thanks for that! Solved loading issues when deploying to Vercel. Not my favorite thing to do but when in a pinch.

@phbernard
Copy link

phbernard commented Jul 7, 2021

Unfortunately, these solutions fail with target: "serverless", which is required by next-on-netlify, for example.

To reproduce the issue, use https://github.com/phbernard/nextjs-react-pdf-sandbox . This sandbox has been forked from @jeetiss's one above (thank you by the way, great resource!), with a change in next.config.js:

module.exports = {
  target: "serverless",
  ...
}

With this project, npm run dev works as expected. However, npm run build fails with:

Failed to compile.

ModuleNotFoundError: Module not found: Error: Can't resolve 'canvas' in '/somewhere/nextjs-react-pdf-sandbox/node_modules/pdfjs-dist/build'

I managed to make it work using webpack externals, still in next.config.js:

module.exports = {
  webpack: (config) => {
    config.externals = {
      ...config.externals,
      canvas: 'canvas',
      critters: 'critters'
    };
   ...
  }
}

Now the project builds and works as expected. However, I get warnings at build time such as:

./node_modules/next/dist/next-server/server/require.js
Critical dependency: the request of a dependency is an expression

This might be harmless, see vercel/next.js#10633 .

I consider this solution as work-in-progress and don't advise to follow it blindly. I put it here because I couldn't find this anywhere.

@oceandrama
Copy link

oceandrama commented Jul 7, 2021

If I try to import components from react-pdf/dist/esm/entry.webpack, I've got the error

Cannot find module 'file-loader!pdfjs-dist/build/pdf.worker'

It's appear even if I add file-loader to next.config.js

Now I'm using worker file from CDN to resolve this

@faberchri
Copy link

I have created a minimal next-js + react-pdf codesandbox and everything works fine with current version, look
https://codesandbox.io/s/react-pdf-next-js-y4ev2

@jeetiss Thanks a lot for your example!
I updated it, so that it no longer relies on the deprecated file-loader plugin but uses Asset Modules. I only adapted next.config.js and removed the no longer needed dependency from package.json.

https://codesandbox.io/s/react-pdf-next-js-forked-x12d2

@asharimh97
Copy link

Unfortunately, these solutions fail with target: "serverless", which is required by next-on-netlify, for example.

To reproduce the issue, use https://github.com/phbernard/nextjs-react-pdf-sandbox . This sandbox has been forked from @jeetiss's one above (thank you by the way, great resource!), with a change in next.config.js:

module.exports = {
  target: "serverless",
  ...
}

With this project, npm run dev works as expected. However, npm run build fails with:

Failed to compile.

ModuleNotFoundError: Module not found: Error: Can't resolve 'canvas' in '/somewhere/nextjs-react-pdf-sandbox/node_modules/pdfjs-dist/build'

I managed to make it work using webpack externals, still in next.config.js:

module.exports = {
  webpack: (config) => {
    config.externals = {
      ...config.externals,
      canvas: 'canvas',
      critters: 'critters'
    };
   ...
  }
}

Now the project builds and works as expected. However, I get warnings at build time such as:

./node_modules/next/dist/next-server/server/require.js
Critical dependency: the request of a dependency is an expression

This might be harmless, see vercel/next.js#10633 .

I consider this solution as work-in-progress and don't advise to follow it blindly. I put it here because I couldn't find this anywhere.

@phbernard I agree, I have tried those solutions but it seems it will still fail with target: serverless. However, when I tried your solution the error changed to:

ModuleNotFoundError: Module not found: Error: Can't resolve 'jimp' in '/path_to_file/node_modules/@ampproject/toolbox-optimizer/lib/transformers'

And when I tried to solve the jimp issue, another error came up:

ModuleNotFoundError: Module not found: Error: Can't resolve 'probe-image-size' in '/path_to_file/node_modules/@ampproject/toolbox-optimizer/lib/transformers'

And lastly, when I tried to put it inside externals the build will give a result error memory heap.

I also have tried to only add externals by "pushing" the canvas with config.externals['canvas'] = 'commonjs canvas' but it seems it doesn't work.

@arnars
Copy link

arnars commented Oct 8, 2021

@asharimh97 did you solve this issues by any chance?

@diakonos
Copy link

I was able to get this working without needing to manually copy the pdf worker file into the public folder by using the copy-webpack-plugin. This will automatically copy the pdf worker file into your public folder when the application builds.

Add something like this to your custom webpack config:

config.plugins.push(
  new CopyPlugin({
    patterns: [
      {
        from: path.join(__dirname, 'node_modules/pdfjs-dist/build/pdf.worker.min.js'),
        to: path.join(__dirname, 'public'),
      },
    ],
  })
);

And update the workerSrc so it checks at the root:

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

@metanivek
Copy link

@arnars @asharimh97 @phbernard I was able to successfully deploy to Netlify using this webpack solution: #799 (comment). Hope that helps!

@GaddMaster
Copy link

@jeetiss - Your shared solution stopped the pain for me. Thanks
Good team effort all
Much appreciation

@MaximeConan
Copy link

Hey guys, for me helped to define JS worker _app.js from CDN.

import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

I used the same method with create-react-app and it works great with Next too. Thanks @adderpositive !

@ghostneneji
Copy link

ghostneneji commented Dec 11, 2021

Hey guys, for me helped to define JS worker _app.js from CDN.

import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

I used the same method with create-react-app and it works great with Next too. Thanks @adderpositive !

with nextjs 12.0.4 this solution worked perfectly for me, and i dont even have to use the dynamic import

@abernier
Copy link

abernier commented May 25, 2022

$ npm i -D copy-webpack-plugin
// next.config.js

const path = require('path')
const CopyPlugin = require("copy-webpack-plugin");

const pdfWorkerPath = require.resolve(
  `pdfjs-dist/build/pdf.worker${
    process.env.NODE_ENV === "development" ? ".min" : ""
  }.js`
);

/** @type {import('next').NextConfig} */
const nextConfig = {
  // ...
  webpack: (config) => {
    config.plugins.push(
      new CopyPlugin({
        patterns: [
          {
            from: pdfWorkerPath,
            to: path.join(__dirname, 'public'),
          },
        ],
      })
    );

    return config;
  },
};

module.exports = nextConfig;

@Genaro-CoronelG
Copy link

Genaro-CoronelG commented May 26, 2022

FYI for others using Next.js they have a helper that we used to work around this issue.

Our problem was that rendering anything which depends on PDF.js server-side will throw errors, as the library itself contains browser API calls which are not safe in Node. By using the above helper to import the component that handles PDF rendering we were able to defer parsing of the library code to the browser, where it ran without error:

// This is our wrapper component which contains the PDF viewer
const PDFViewer = dynamic(import('../../components/PDFViewer'), { ssr: false });

class ExampleClass extends Component {
  render() {
    return (
      <div>
        <PDFViewer />
      </div>
    );
  }
}

Thank you, this works for me!

@github-actions
Copy link
Contributor

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this issue will be closed in 14 days.

@github-actions github-actions bot added the stale label Aug 29, 2022
@github-actions
Copy link
Contributor

This issue was closed because it has been stalled for 14 days with no activity.

@silarce
Copy link

silarce commented Sep 15, 2022

$ npm i -D copy-webpack-plugin
// next.config.js

const path = require('path')
const CopyPlugin = require("copy-webpack-plugin");

const pdfWorkerPath = require.resolve(
  `pdfjs-dist/build/pdf.worker${
    process.env.NODE_ENV === "development" ? ".min" : ""
  }.js`
);

/** @type {import('next').NextConfig} */
const nextConfig = {
  // ...
  webpack: (config) => {
    config.plugins.push(
      new CopyPlugin({
        patterns: [
          {
            from: pdfWorkerPath,
            to: path.join(__dirname, 'public'),
          },
        ],
      })
    );

    return config;
  },
};

module.exports = nextConfig;

@abernier
it's work
I thank you so much

@mdtaju

This comment was marked as off-topic.

@xtealer

This comment was marked as off-topic.

@TheNewLad

This comment was marked as off-topic.

@pagarevijayy
Copy link

pagarevijayy commented Sep 20, 2023

I have created a minimal next-js + react-pdf codesandbox and everything works fine with current version, look

https://codesandbox.io/s/react-pdf-next-js-y4ev2

bro @jeetiss, how do you deploy this solution on vercel??

it's giving me build error -

Failed to compile.
static/worker/b77d775811fc6a2622a0bd60bf2d810d.js from Terser
Unexpected character '#' [static/worker/b77d775811fc6a2622a0bd60bf2d810d.js:22,25236]

Build failed because of webpack errors

any help anyone?

@pagarevijayy
Copy link

Hey guys, for me helped to define JS worker _app.js from CDN.

import { pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

I used the same method with create-react-app and it works great with Next too. Thanks @adderpositive !

with nextjs 12.0.4 this solution worked perfectly for me, and i dont even have to use the dynamic import

@ghostneneji did it get deployed? I'm facing issue in deployment on vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested stale
Projects
None yet
Development

No branches or pull requests