wojtekmaj / react-pdf

Display PDFs in your React app as easily as if they were images.
https://projects.wojtekmaj.pl/react-pdf
MIT License
9.58k stars 898 forks source link

Config worker not work when using Vite + React.lazy + react-pdf #1843

Open nmaddp1995 opened 4 months ago

nmaddp1995 commented 4 months ago

Before you start - checklist

Description

I face the problem that shows Setting fake worker failed when using Vite + React.lazy (for react-pdf component) + run build mode image

This issue only happen when run in npm run build mode, not happen when run in npm run dev mode Previously I used Webpack and this issue did not happen. It just happen when I migrate to vite

Steps to reproduce

https://github.com/nmaddp1995/react-pdf-vite-lazy-issue Step1: Config worker in main file Step2: Import component ReactPDF with Lazy: image

image

Run this repo in production mode (npm run build) View the app by npm run preview Compare with run the app by npm run dev build

Production build: image

Dev run: image

Expected behavior

It should work the same with npm run dev and npm run build mode

Actual behavior

Production build: image

Dev run: image

Additional information

No response

Environment

lotfiGipsyKing commented 4 months ago

Hello i managed to fix this issue, by adding a custom vite plugin to copy the pdf-worker in the dist folder:

vite.config.ts

// custom plugin to copy pdf worker
const copyPdfWorkerPlugin = (): Plugin => ({
  name: 'copy-pdf-worker',
  apply: 'build',
  configResolved(config) {
    const pdfjsDistPath = path.dirname(require.resolve('pdfjs-dist/package.json'));
    const pdfWorkerPath = path.join(pdfjsDistPath, 'build', 'pdf.worker.mjs');
    fs.cpSync(pdfWorkerPath, './dist/pdf.worker.mjs', { recursive: true });
  },
});

// then add it to your plugins list
export default defineConfig({
  plugins: [copyPdfWorkerPlugin()],
}
lotfiGipsyKing commented 4 months ago

If you are using a nginx in production, the problem came probably from your nginx config, because is not serving the .mjs files.

The solution is to update your nginx config to serve them as a javascript files, to do so, this an example:

http {
    # Includes mapping of file name extensions to MIME types of responses
    # and defines the default type.
    include /etc/nginx/mime.types;
    # maps the js and mjs file extensions to the application/javascript MIME type.
    types {
        application/javascript js mjs;
    }
    default_type application/octet-stream;
}
ernst77 commented 3 months ago

If you are using a nginx in production, the problem came probably from your nginx config, because is not serving the .mjs files.

The solution is to update your nginx config to serve them as a javascript files, to do so, this an example:

http {
  # Includes mapping of file name extensions to MIME types of responses
  # and defines the default type.
  include /etc/nginx/mime.types;
  # maps the js and mjs file extensions to the application/javascript MIME type.
  types {
      application/javascript js mjs;
  }
  default_type application/octet-stream;
}

Thank you, this helped, had to add mjs to all nginx proxies

moyarich commented 2 months ago

This did not work for me:

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


I got it to work by placing pdf.worker.min.mjs in the public folder of my web app


Added to main.tsx


import { pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.mjs";


I am using projen, so this is my configuration.
In .projenrc.ts, I added:
 


// Add "prebuild" script settings to package.json

const pdfjs_dist = webapp.addTask("prebuild", {

    description: "For React-PDF [wojtekmaj/react-pdf] to work",
    exec: `cp ${path.relative(webapp.outdir, path.join(require.resolve("pdfjs-dist"), "..", "pdf.worker.min.mjs"))} public/pdf.worker.min.mjs`,
    receiveArgs: true,
});

// automatically run "prebuild" script when web-app:build gets called via  "npx nx run web-app:build --skip-nx-cache"

webapp.tasks.tryFind("build")?.prependSpawn(pdfjs_dist);
webapp.gitignore.addPatterns("public/pdf.worker.min.mjs");

// Add settings to .npmrc - enables pnpm pre-post scripts to automatically run via "pnpm build"
project.npmrc.addConfig("enable-pre-post-scripts", "true");
yaswanthmaddula-sureify commented 1 month ago

Any update ?

tiennguyen1293 commented 1 month ago

I am facing this issue also, and followed steps but it did not work, and my nginx.conf file:

http {
    include /etc/nginx/mime.types;

        types {
          application/javascript js mjs;
        }

        default_type application/octet-stream;

        server {
              gzip on;
              gzip_disable "msie6";
              gzip_vary on;
              gzip_proxied any;
              gzip_comp_level 6;
              gzip_buffers 16 8k;
              gzip_min_length 256;
              gzip_types
                text/plain
                text/css
                text/js
                text/xml
                text/javascript
                application/javascript
                application/x-javascript
                application/json
                application/xml
                application/rss+xml
                image/svg+xml;
           ...
        }
}

Anyone have another idea?

ernst77 commented 1 month ago

I am facing this issue also, and followed steps but it did not work, and my nginx.conf file:

http {
  include /etc/nginx/mime.types;

        types {
          application/javascript js mjs;
        }

        default_type application/octet-stream;

        server {
              gzip on;
              gzip_disable "msie6";
              gzip_vary on;
              gzip_proxied any;
              gzip_comp_level 6;
              gzip_buffers 16 8k;
              gzip_min_length 256;
              gzip_types
                text/plain
                text/css
                text/js
                text/xml
                text/javascript
                application/javascript
                application/x-javascript
                application/json
                application/xml
                application/rss+xml
                image/svg+xml;
           ...
        }
}

Anyone have another idea?

I edited mime.types file in nginx config ( yours is in /etc/nginx/mime.types;)

replaced js line with this application/javascript js mjs;

yaswanthmaddula-sureify commented 1 month ago

I had to configure the worker again in the pdf viewer component in useEffect.

tiennguyen1293 commented 1 month ago

I am facing this issue also, and followed steps but it did not work, and my nginx.conf file:

http {
    include /etc/nginx/mime.types;

        types {
          application/javascript js mjs;
        }

        default_type application/octet-stream;

        server {
              gzip on;
              gzip_disable "msie6";
              gzip_vary on;
              gzip_proxied any;
              gzip_comp_level 6;
              gzip_buffers 16 8k;
              gzip_min_length 256;
              gzip_types
                text/plain
                text/css
                text/js
                text/xml
                text/javascript
                application/javascript
                application/x-javascript
                application/json
                application/xml
                application/rss+xml
                image/svg+xml;
           ...
        }
}

Anyone have another idea?

I edited mime.types file in nginx config ( yours is in /etc/nginx/mime.types;)

replaced js line with this application/javascript js mjs;

I updated but it isn't working.

pdfjs.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs'
http {
    include mime.types;

        types {
          application/javascript js mjs;
        }

        default_type application/octet-stream;

        server {
              gzip on;
              gzip_disable "msie6";
              gzip_vary on;
              gzip_proxied any;
              gzip_comp_level 6;
              gzip_buffers 16 8k;
              gzip_min_length 256;
              gzip_types
                text/plain
                text/css
                text/xml
                text/javascript
                application/javascript
                application/x-javascript
                application/json
                application/xml
                application/rss+xml
                image/svg+xml;
           ...
        }
}

image

abdel7ak96 commented 1 month ago

Solution

Using: Vite + React.lazy

I had the same issue, what solved it for me: is configuring PDF.js worker inside a self-invoked function and importing pdfjs in there:

// src/main.tsx

// Configure PDF.js worker
(async () => {
  const { pdfjs } = await import("react-pdf");
  pdfjs.GlobalWorkerOptions.workerSrc = new URL(
    "pdfjs-dist/build/pdf.worker.min.mjs",
    import.meta.url
  ).toString();
})();

This also works, because I think the issue was not having pdfjs used anywhere and consequently not loaded.

// src/main.tsx

import { pdfjs } from "react-pdf"; 

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

console.log(pdfjs);