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 compatible without shims #3405

Closed
6 tasks done
thekevinbrown opened this issue May 13, 2021 · 11 comments
Closed
6 tasks done

react-pdf is not compatible without shims #3405

thekevinbrown opened this issue May 13, 2021 · 11 comments

Comments

@thekevinbrown
Copy link

thekevinbrown commented May 13, 2021

Describe the bug

When trying to use React PDF in a Vite React project, we get:

Uncaught ReferenceError: global is not defined
    at node_modules/blob/index.js (index.js:5)
    at __require (chunk-KVFJW2XH.js?v=ce5c473e:12)
    at node_modules/blob-stream/index.js (index.js:3)
    at __require (chunk-KVFJW2XH.js?v=ce5c473e:12)
    at asyncToGenerator.js:32

It's from the blob NPM library, but what's really strange is the code in .vite/@react-pdf_renderer.js on line 554 is:

var BlobBuilder = global.BlobBuilder || global.WebKitBlobBuilder || global.MSBlobBuilder || global.MozBlobBuilder;

But the module definitely does not get packaged with references to global: https://unpkg.com/blob@0.1.0/main.js

We'd like to understand where the global is coming from, then be able to fix and/or work around this so that we can use React PDF in our project.

Also noteworthy is that when we try to use Document, Page, or other exports that the TypeScript types say should be there, we get:

Uncaught SyntaxError: The requested module '/node_modules/.vite/@react-pdf_renderer.js?v=ce5c473e' does not provide an export named 'Document'

It really makes me wonder if we're somehow selecting a server version of React PDF, but I can't see how or where that's happening in the monorepo imports that are going on.

Reproduction

https://github.com/thekevinbrown/vite-react-pdf-reproduction

System Info

Output of npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers:

  System:
    OS: macOS 11.2.3
    CPU: (8) arm64 Apple M1
    Memory: 541.69 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 15.11.0 - ~/.nvm/versions/node/v15.11.0/bin/node
    Yarn: 1.22.5 - ~/.yarn/bin/yarn
    npm: 7.6.0 - ~/.nvm/versions/node/v15.11.0/bin/npm
  Browsers:
    Brave Browser: 90.1.23.75
    Chrome: 90.0.4430.212
    Firefox: 88.0
    Safari: 14.0.3
  npmPackages:
    vite: ^2.3.0 => 2.3.2 

Used package manager: yarn

Logs

$ vite --debug
  vite:config bundled config file loaded in 33ms +0ms
  vite:config using resolved config: {
  vite:config   plugins: [
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'react-refresh',
  vite:config     'vite:dynamic-import-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:client-inject',
  vite:config     'vite:import-analysis'
  vite:config   ],
  vite:config   server: {
  vite:config     fsServe: {
  vite:config       root: '/Users/kevin/development/vite-react-pdf-reproduction',
  vite:config       strict: false
  vite:config     }
  vite:config   },
  vite:config   configFile: '/Users/kevin/development/vite-react-pdf-reproduction/vite.config.ts',
  vite:config   configFileDependencies: [ 'vite.config.ts' ],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     server: { fsServe: [Object] }
  vite:config   },
  vite:config   root: '/Users/kevin/development/vite-react-pdf-reproduction',
  vite:config   base: '/',
  vite:config   resolve: { dedupe: undefined, alias: [ [Object] ] },
  vite:config   publicDir: '/Users/kevin/development/vite-react-pdf-reproduction/public',
  vite:config   cacheDir: '/Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite',
  vite:config   command: 'serve',
  vite:config   mode: 'development',
  vite:config   isProduction: false,
  vite:config   build: {
  vite:config     target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     minify: 'terser',
  vite:config     terserOptions: {},
  vite:config     cleanCssOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     brotliSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null
  vite:config   },
  vite:config   env: { BASE_URL: '/', MODE: 'development', DEV: true, PROD: false },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen]
  vite:config   },
  vite:config   createResolver: [Function: createResolver],
  vite:config   optimizeDeps: { esbuildOptions: { keepNames: undefined } }
  vite:config } +2ms
  vite:deps Hash is consistent. Skipping. Use --force to override. +0ms

  vite v2.3.2 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 139ms.

  vite:time 1ms   / +0ms
  vite:spa-fallback Rewriting GET / to /index.html +0ms
  vite:time 19ms  /index.html +36ms
  vite:resolve 1ms   /Users/kevin/development/vite-react-pdf-reproduction/node_modules/vite/dist/client/client -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/vite/dist/client/client.js +0ms
  vite:resolve 2ms   /@vite/client -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/vite/dist/client/client.js +0ms
  vite:resolve 0ms   /src/main.tsx -> /Users/kevin/development/vite-react-pdf-reproduction/src/main.tsx +2ms
  vite:load 2ms   [fs] /@vite/client +0ms
  vite:resolve 1ms   ./env -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/vite/dist/client/env.js +9ms
  vite:resolve 0ms   /node_modules/vite/dist/client/env.js -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/vite/dist/client/env.js +0ms
  vite:transform 7ms   /@vite/client +0ms
  vite:time 14ms  /@vite/client +45ms
  vite:load 10ms  [fs] /src/main.tsx +9ms
  vite:load 0ms   [plugin] /@react-refresh +140ms
  vite:rewrite 1ms   [no imports] /@react-refresh +0ms
  vite:transform 1ms   /@react-refresh +141ms
  vite:time 1ms   /@react-refresh +141ms
  vite:resolve 0ms   react -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/react.js?v=ce5c473e&es-interop +146ms
  vite:resolve 0ms   /node_modules/.vite/react.js?v=ce5c473e&es-interop -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/react.js?v=ce5c473e&es-interop +0ms
  vite:resolve 0ms   react-dom -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/react-dom.js?v=ce5c473e&es-interop +2ms
  vite:resolve 0ms   /node_modules/.vite/react-dom.js?v=ce5c473e&es-interop -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/react-dom.js?v=ce5c473e&es-interop +0ms
  vite:resolve 0ms   ./App -> /Users/kevin/development/vite-react-pdf-reproduction/src/App.tsx +0ms
  vite:resolve 0ms   /src/App.tsx -> /Users/kevin/development/vite-react-pdf-reproduction/src/App.tsx +0ms
  vite:resolve 0ms   /node_modules/.vite/react.js?v=ce5c473e -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/react.js?v=ce5c473e +0ms
  vite:resolve 0ms   /node_modules/.vite/react-dom.js?v=ce5c473e -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/react-dom.js?v=ce5c473e +0ms
  vite:transform 147ms /src/main.tsx +6ms
  vite:time 158ms /src/main.tsx +7ms
  vite:load 0ms   [fs] /node_modules/vite/dist/client/env.js +8ms
  vite:rewrite 0ms   [no imports] node_modules/vite/dist/client/env.js +8ms
  vite:transform 0ms   /node_modules/vite/dist/client/env.js +2ms
  vite:time 1ms   /node_modules/vite/dist/client/env.js +1ms
  vite:load 1ms   [fs] /src/App.tsx +8ms
  vite:resolve 0ms   @react-pdf/renderer -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/@react-pdf_renderer.js?v=ce5c473e +16ms
  vite:resolve 0ms   /node_modules/.vite/@react-pdf_renderer.js?v=ce5c473e -> /Users/kevin/development/vite-react-pdf-reproduction/node_modules/.vite/@react-pdf_renderer.js?v=ce5c473e +0ms
  vite:hmr [self-accepts] src/App.tsx +0ms
  vite:transform 8ms   /src/App.tsx +15ms
  vite:time 10ms  /src/App.tsx +16ms
  vite:time 2ms   /src/favicon.svg +163ms
  vite:spa-fallback Rewriting GET / to /index.html +7s
  vite:time 4ms   /index.html +6s
  vite:cache [304] /@vite/client +0ms
  vite:time 2ms   /@vite/client +38ms
  vite:cache [304] /src/main.tsx +1ms
  vite:time 1ms   /src/main.tsx +2ms
  vite:cache [304] /@react-refresh +15ms
  vite:time 0ms   /@react-refresh +14ms
  vite:cache [304] /node_modules/vite/dist/client/env.js +2ms
  vite:time 1ms   /node_modules/vite/dist/client/env.js +2ms
  vite:cache [304] /src/App.tsx +3ms
  vite:time 1ms   /src/App.tsx +3ms
  vite:time 1ms   /src/favicon.svg +161ms

Before submitting the issue, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the docs.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Provide a description in this issue that describes the bug.
  • Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/vue-next instead.
  • Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
@Niputi
Copy link
Contributor

Niputi commented May 13, 2021

could you try following this comment #2618 (comment)

@thekevinbrown
Copy link
Author

@Niputi when I do that, I then get none of the expected exports from the library, e.g.

Uncaught SyntaxError: The requested module '/node_modules/.vite/@react-pdf_renderer.js?v=ce5c473e' does not provide an export named 'PDFRenderer'

or what I'm actually after:

Uncaught SyntaxError: The requested module '/node_modules/.vite/@react-pdf_renderer.js?v=ce5c473e' does not provide an export named 'Document'

@Niputi
Copy link
Contributor

Niputi commented May 13, 2021

It looks like the file 'react-pdf.browser.es.js' does not provide a export for 'Document'.

I tried using the plugin-cdn by following this guide with the following config

cdn('skypack', {
  '@react-pdf/renderer': '^2.0.12'
})

by doing this I got this error message

Uncaught SyntaxError: The requested module '/-/restructure@v0.5.4-1x0iZnKm3JkZFlHtuxoO/dist=es2020,mode=imports/unoptimized/src/utils.js' does not provide an export named 'PropertyDescriptor'

It seems like esm version of @react-pdf_renderer is broken by including node specific code and not including all necessary exports. you should make a bug report the library

@nihalgonsalves
Copy link
Member

nihalgonsalves commented May 13, 2021

Looks like it isn't compatible with Webpack 5 either: diegomura/react-pdf#1029

Another issue, as @Niputi pointed out, seems to be that the export * from '@react-pdf/primitives' does not seem to be preserved in react-pdf's es bundle: https://github.com/diegomura/react-pdf/blob/235dc0a/packages/renderer/src/dom.js#L171

  • node_modules/@react-pdf/renderer/lib/react-pdf.browser.es.js

    Has the primitives on the default export, but not the named exports:
    // ...
    
    var dom = _extends({
      pdf: pdf,
      usePDF: usePDF,
      Font: Font,
      version: version,
      StyleSheet: StyleSheet,
      PDFViewer: PDFViewer,
      BlobProvider: BlobProvider,
      PDFDownloadLink: PDFDownloadLink,
      renderToStream: renderToStream,
      renderToString: renderToString,
      renderToFile: renderToFile,
      render: render
    }, primitives);
    
    export default dom;
    export { BlobProvider, Font, PDFDownloadLink, PDFViewer, StyleSheet, createRenderer, pdf, render, renderToFile, renderToStream, renderToString, usePDF, version };
    //# sourceMappingURL=react-pdf.browser.es.js.map

Combining the shims from the linked issue, a shim for EventEmitter, and using the default export, I was able to get it to work:

  • Patch: thekevinbrown:vite-react-pdf-reproduction-391f8ab.patch.txt (use git apply path/to/patch on your reproduction repo).

  • Inline Diff

    diff --git a/index.html b/index.html
    index 38f3861..7e9e3e4 100644
    --- a/index.html
    +++ b/index.html
    @@ -7,6 +7,16 @@
        <title>Vite App</title>
        </head>
        <body>
    +    <script type="module">
    +      import process from "process";
    +      import { Buffer } from "buffer";
    +      import EventEmitter from "events";
    +
    +      window.global = window;
    +      window.Buffer = Buffer;
    +      window.process = process;
    +      window.EventEmitter = EventEmitter;
    +    </script>
        <div id="root"></div>
        <script type="module" src="/src/main.tsx"></script>
        </body>
    diff --git a/package.json b/package.json
    index a7033ef..e2ee76f 100644
    --- a/package.json
    +++ b/package.json
    @@ -9,8 +9,15 @@
        },
        "dependencies": {
        "@react-pdf/renderer": "^2.0.12",
    +    "assert": "^2.0.0",
    +    "browserify-zlib": "^0.2.0",
    +    "buffer": "^6.0.3",
    +    "events": "^3.3.0",
    +    "process": "^0.11.10",
        "react": "^17.0.0",
    -    "react-dom": "^17.0.0"
    +    "react-dom": "^17.0.0",
    +    "stream-browserify": "^3.0.0",
    +    "util": "^0.12.3"
        },
        "devDependencies": {
        "@types/react": "^17.0.0",
    diff --git a/src/App.tsx b/src/App.tsx
    index e2056f6..0a8ea07 100644
    --- a/src/App.tsx
    +++ b/src/App.tsx
    @@ -1,4 +1,35 @@
    import React from "react";
    -import { PDFViewer } from "@react-pdf/renderer";
    +import ReactPDFRenderer, { PDFViewer } from "@react-pdf/renderer";
    
    -export const App = () => <PDFViewer />;
    +const { Document, Page, View, Text, StyleSheet } = ReactPDFRenderer;
    +
    +const styles = StyleSheet.create({
    +  page: {
    +    flexDirection: "row",
    +    backgroundColor: "#E4E4E4",
    +  },
    +  section: {
    +    margin: 10,
    +    padding: 10,
    +    flexGrow: 1,
    +  },
    +});
    +
    +const MyDocument = () => (
    +  <Document>
    +    <Page size="A4" style={styles.page}>
    +      <View style={styles.section}>
    +        <Text>Section #1</Text>
    +      </View>
    +      <View style={styles.section}>
    +        <Text>Section #2</Text>
    +      </View>
    +    </Page>
    +  </Document>
    +);
    +
    +export const App = () => (
    +  <PDFViewer>
    +    <MyDocument />
    +  </PDFViewer>
    +);
    diff --git a/vite.config.ts b/vite.config.ts
    index 5e7342c..7677366 100644
    --- a/vite.config.ts
    +++ b/vite.config.ts
    @@ -3,5 +3,12 @@ import reactRefresh from '@vitejs/plugin-react-refresh'
    
    // https://vitejs.dev/config/
    export default defineConfig({
    -  plugins: [reactRefresh()]
    -})
    +  resolve: {
    +    alias: {
    +      process: "process/browser",
    +      stream: "stream-browserify",
    +      zlib: "browserify-zlib",
    +    },
    +  },
    +  plugins: [reactRefresh()],
    +});
    

@nihalgonsalves nihalgonsalves changed the title Blob NPM module expects Node context in Vite react-pdf is not compatible without shims May 13, 2021
@nihalgonsalves
Copy link
Member

nihalgonsalves commented May 13, 2021

Closing this since it isn't something Vite can fix.

@thekevinbrown
Copy link
Author

That is amazing, thank you so much for your help!

@thekevinbrown
Copy link
Author

thekevinbrown commented Jun 4, 2021

Ok, I'm incredibly stuck. This workaround works fine in dev but not in production. This is because the script in index.html gets pulled into the index bundle, but the shims are required for vendor. Vendor is preloaded, so it loads before the shims.

Here's what I've tried:

  • Using @rollup/plugin-inject to see if I can get the shims in that way. No dice, Vite starts saying:
8:36:23 PM [vite] Internal server error: ENOENT: no such file or directory, open '[project]/node_modules/.vite/browser-external:util'

I cannot figure out why that file isn't there. The util module is in node_modules.

  • Removing node code from React PDF. I spent 6 hours on this and couldn't fix it all.
  • Creating my own vite plugin to inject the shims. Problem is I don't know how to import in this context and get it actually working.
  • I even tried using vite-plugin-banner to try to inject stuff. No good, nor should it be, that's gross.

Does anyone know how I can get these shims injected at the top of the vendor bundle, referencing the correct browserify packages?

Edit: I also tried:

export default function inject() {
  return {
    name: "inject-react-pdf-shims",
    enforce: "pre",

    transform(code, id) {
      if (/@react-pdf_renderer/.test(id)) {
        return {
          code: `
import process from "process";
import { Buffer } from "buffer";
import EventEmitter from "events";

window.global = window;
window.Buffer = Buffer;
window.process = process;
window.EventEmitter = EventEmitter;
${code}
`,
        };
      }
    },
  };
}

but no dice either:

Uncaught SyntaxError: The requested module '/node_modules/buffer/index.js?v=08612583' does not provide an export named 'Buffer'

It's CJS, so I don't know how to import it there.

@thekevinbrown
Copy link
Author

thekevinbrown commented Jun 5, 2021

Alrighty, finally found a set of shims and workarounds that make it work, both in Vite Dev and Production builds.

So, if you're coming here from Google, you do the following in your Vite project:

$ yarn add --dev vite-plugin-shim-react-pdf

Then in vite.config.js:

import { defineConfig } from "vite";
import reactRefresh from "@vitejs/plugin-react-refresh";
import shimReactPdf from "vite-plugin-shim-react-pdf";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [reactRefresh(), shimReactPdf()],
});

The you'll also need to use the default import because of the missing exports. E.g.

Instead of:

import { Text, View, StyleSheet } from "@react-pdf/renderer";

You have to do:

import pdf from "@react-pdf/renderer";
const { Text, View, StyleSheet } = pdf;

React PDF also didn't have a development project you could use to test changes, so I made a really rough one out of the examples: https://github.com/TechInSite/react-pdf-development-harness

@Cslove
Copy link

Cslove commented Jun 6, 2021

@thekevinbrown thank you so much!! meet same problem. and your vite plugin solved my issue! by the way, it should yarn add vite-plugin-shim-react-pdf -D, thanks again!

@thekevinbrown
Copy link
Author

Thanks @Cslove, you're right. I updated the instructions above to add --dev to the command

@github-actions
Copy link

This issue has been locked since it has been closed for more than 14 days.

If you have found a concrete bug or regression related to it, please open a new bug report with a reproduction against the latest Vite version. If you have any other comments you should join the chat at Vite Land or create a new discussion.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 15, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants