danomatic/react-pdf-html

Package doesn't work on Node server

Closed this issue · 4 comments

I'm using @react-pdf/renderer on a backend Node server and trying to render some html in the pdf using react-pdf-html. However I get this error:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

Is it possible to use react-pdf-html on the server?

gla23 commented

We worked out that this was caused by a mismatch in the types provided in the package. The .TypeScript warning lead us to do the wrong import which generated the error above.

I think there is an error in your types (the Html.d.ts file provided by npm).

When inspecting node_modules, the Html.d.ts has export default Html; but Html.js has exports.default = Html;.
I think the types are saying that the package provides a ESM default export, where in reality the vanilla JS exports a CommonJS module.

When we used this on the frontend with with Vite it worked fine. I think Vite handles the mismatch; that is, it gives us the ESM default export, rather than the CommonJS module. However, when using Node we have to do the following it to correctly use the Html component:

import pkg from "react-pdf-html";
const Html = (pkg as any).Html

This makes sense given the code snippets above.

Our issue is fixed, but reporting anyway incase others have the same issue, and it may be helpful for fixing the types.

@gla23 thanks for the input. Is there a changed needed for this package to help with this?

Thank you @gla23! That solved my issue. I am curious if this can be easily remedied in the package, but I'll admit to being too inexperienced to know what to change.

I think there is an error in your types (the Html.d.ts file provided by npm).

When inspecting node_modules, the Html.d.ts has export default Html; but Html.js has exports.default = Html;. I think the types are saying that the package provides a ESM default export, where in reality the vanilla JS exports a CommonJS module.

Could this be fixed with a missing property in the tsconfig or package.json? I'll be digging into this over the weekend to satisfy my own curiosity.

Reporting back after a weekend of research and an ambitious PR submission!

The package is currently written in CommonJS as is the build output. The types are unchanged by which module build is chosen, but if you're importing react-pdf-html into a TypeScript Node app that is ESM, the compiler will expect ESM (but find CommonJS instead).

By default, CommonJS modules build CommonJS, and so do ES modules. In this way, ESM is backward-compatible with CJS, but CJS cannot compile to ESM. In the interest of getting react-pdf-html "future-ready" and ESM compatible, refactoring the package to ESM has its merits and can be done with relatively minimal changes to the current dependencies and configurations.

@gla23 thanks for the input. Is there a changed needed for this package to help with this?

@danomatic, please see the proposed changes in #81.

While @gla23's workaround solves the import into an ES module Node app, this package could benefit from being rewritten as an ES module to increase its flexibility. In the interest of getting react-pdf-html "future-ready" and ESM compatible, refactoring the package to ESM has its merits.