Search code examples
javascriptnode.jstypescriptcreate-react-app

Typescript library can only compile for react or for node, but not both at the same time


I have a yarn workspace with a typescript nodejs server and a typescript react client (using create react app). I also have a common typescript library, but no matter what I can't seem to get it to compile for both at the same time.

I'm not a javascript expert by any standard.

This is the index.ts for the common project:

export * from "./interfaces/AuthModels"

This is part of the package.json:

{
    "main": "dist/index.js",
    "types": "dist/index.d.ts",
}

If I set the following for the common tsconfig.json it will compile for nodejs:

{
    "compilerOptions": {
        "target": "esnext",
        "module": "commonjs",
        "moduleResolution": "node",
    },
}

But then I get the following error when running the react app:

Uncaught TypeError: h.keyframes is not a function
    at ../../node_modules/react-hot-toast/dist/index.js (error.tsx:3:1)
    at options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at ../common/dist/components/Notifications.js (Notifications.js:5:1)
    at options.factory (react refresh:6:1)
    at __webpack_require__ (bootstrap:24:1)
    at fn (hot module replacement:62:1)
    at ../common/dist/index.js (index.js:25:1)
    at options.factory (react refresh:6:1)

If I change the following to tsconfig.json it will compile for react, but not nodejs:

{
    "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "moduleResolution": "node",
    },
}

I get the following error running it on nodejs:

export * from "./interfaces/AuthModels";
^^^^^^

SyntaxError: Unexpected token 'export'

Solution

  • You will need to factor out any of the parts of the library that use browser APIs not present in node.js, or gate access behind appropriate conditional checks like so:

    if (typeof window !== 'undefined') {
        // do browser stuff
    }
    

    The "h.keyframes is not a function" error is telling you that something you are including isn't node.js compatible.

    Once you've done that, you will want to compile the Typescript to the commonjs module format (CJS). Those can run directly in node.js, and since you're using create-react-app you'll have Webpack to bundle it for the browser side. That will fix your "unexpected token 'export'" error.