diegomura / diegomura/react-pdf
React-PDF Unusable For Modern Packaging Systems & Server Side Rendering
- Dominant language
- TypeScript
- Stars
- 16.8k
- Forks
- 1.3k
- Avg merge
- 5h 6m
- Merged PRs (30d)
- 52
Description
There are multiple issues here, please read carefully. This should probably be broken into multiple issues but consolidating here to keep it simple for me.
The issues described here will also resolve: #2599 & #2623
## React-PDF Unusable for Modern Packaging Systems
This one is a little frustrating, please take some time to read the documentation for how ESM modules work:
https://nodejs.org/api/packages.html#package-entry-points
**TLDR;**
**The current `exports` of `@react-pdf/renderer` has no browser entry making it _impossible_ for a project which respects ESM modules to work in the browser.**
Additionally, if you're going to bundle both CommonJS and ES Module files in the same package, please use `.mjs` file extensions. Setting `"type": "module"` in the package isn't exactly accurate because the package could be used as a CommonJS package and not just an ES Module. More importantly, if you're going to continue to use `.js` file extensions, please reserve that for the CommonJS files.
Here is what I think you should target in `@react-pdf/renderer/package.json`
```jsonc
// This is an exception to not using .js for ES modules, but this could be phased out over time
// If the bundling system actually respects ES Modules it will completely ignore this field
// and instead use "exports" entry
// Note: This file is identical to ./lib/react-pdf.modern.mjs
"module": "./lib/react-pdf.legacy-esm.js",
"main": "./lib/cjs/react-pdf.js",
"types": "./lib/index.d.ts",
"sideEffects": false, // (hopefully?)
"exports": {
".": {
"types": "./lib/index.d.ts",
"node": {
"import": "./lib/react-pdf.modern.mjs",
"default": "./lib/cjs/react-pdf.js"
},
"browser": {
"import": "./lib/react-pdf.browser.modern.mjs",
"default": "./lib/cjs/react-pdf.browser.js"
},
"default": {
"import": "./lib/react-pdf.modern.mjs",
"default": "./lib/cjs/react-pdf.js"
}
}
},
```
Note: While I only documented it for `@react-pdf/renderer`, this would be required for every package.
## React-PDF Unusable for Server Side Rendering
This one is a little more complicated and will require actual changes in the code.
In short, when using a server side rendering framework like NextJS your code is run twice, once on the server to generate a (typically) reusable [pre]rendered page which is served for incoming requests. The second is in the browser where the code is actually running for its intended purpose.
If you look at the generated output from a NextJS build, you will actually see two different bundles:
1) `server/chunks` -> Used for running on the server to generate the pre-rendered page
2) `static/chunks` -> Served to the client for running in the browser
#### The problem
When NextJS builds the bundle for `server/chunks` it uses the [default](https://nodejs.org/api/esm.html#resolution-algorithm) [conditions](https://nodejs.org/api/packages.html#conditional-exports) of `["node", "import"]`
Therefore the server side bundle will _always_ receive the node version of the package causing legitimate uses (eg. `usePDF`) of the package to break.
To be honest, it also seems to me that you are abusing the `"browser"` convention of bundlers. You are not providing an "alternate" implementation targeted for the browser environment, you are providing a _completely different implementation_.
Further, if I wanted to render the PDF to a stream or buffer on the browser, why are you preventing me? If I needed to send the PDF to the server, that is exactly what I would look to do.
## Work Arounds
If you are landing on this issue and think it pertains to you, there are no work arounds.
Your only solution (for now) is specifying resolutions for all packages under `@react-pdf`
```json
"resolutions": {
"@react-pdf/fns": "2.0.1",
"@react-pdf/font": "2.3.7",
"@react-pdf/image": "2.2.2",
"@react-pdf/layout": "3.6.3",
"@react-pdf/pdfkit": "3.0.2",
"@react-pdf/png-js": "2.2.0",
"@react-pdf/primitives": "3.0.1",
"@react-pdf/render": "3.2.7",
"@react-pdf/renderer": "3.1.14",
"@react-pdf/stylesheet": "4.1.8",
"@react-pdf/textkit": "4.2.0",
"@react-pdf/types": "2.3.4",
"@react-pdf/yoga": "4.1.2"
},
```
Final thought:
diegomura wojtekmaj - Thank you for creating this module, it is actually pretty useful. All criticism with :heart:
Contributor guide
Assessment
This issue has not been assessed yet.