Search code examples
react-pdfesbuild

How do you shim react-pdf with esbuild?


If you bundle react-pdf for the browser using esbuild today you will run into errors that prompt you to build for platform=node because zlib and stream are not available in the browser environment.

I did find a conversation around how to swap this when using vite but I'm curious if others have created a shim for esbuild that offers something equivalent

process: "process/browser",
stream: "vite-compatible-readable-stream",
zlib: "browserify-zlib"

the version I'm using today: @react-pdf/renderer": "^2.0.21"

edit

It just so happens a node modules polyfill exists for esbuild and you should be able to configure this as a plugin

https://github.com/remorses/esbuild-plugins#readme

npm i -D @esbuild-plugins/node-globals-polyfill

and then w/ esbuild you can pass it in like so

https://esbuild.github.io/plugins/#using-plugins

More after I confirm this is working end to end


Solution

  • I was able to achieve this using esbuild v0.14.10 and 2 plugins

    npm i -D @esbuild-plugins/node-modules-polyfill
    npm i -D @esbuild-plugins/node-globals-polyfill
    

    With a build configuration like this

    const esbuild = require('esbuild')
    const globalsPlugin = require('@esbuild-plugins/node-globals-polyfill')
    const modulesPlugin = require('@esbuild-plugins/node-modules-polyfill')
    
    const args = process.argv.slice(2)
    const deploy = args.includes('--deploy')
    
    const loader = {
      // Add loaders for images/fonts/etc, e.g. { '.svg': 'file' }
    }
    
    const plugins = [
      globalsPlugin.NodeGlobalsPolyfillPlugin({
          process: true,
          buffer: true,
          define: { 'process.env.NODE_ENV': deploy ? '"production"' : '"development"' },
      }),
      modulesPlugin.NodeModulesPolyfillPlugin(),
    ]
    
    let opts = {
      entryPoints: ['js/app.js'],
      bundle: true,
      target: 'es2017',
      outdir: '../priv/static/assets',
      logLevel: 'info',
      inject: ['./react-shim.js'],
      loader,
      plugins
    }
    
    if (deploy) {
      opts = {
        ...opts,
        minify: true
      }
    }
    
    const promise = esbuild.build(opts)