Edit: Maybe you can tell me in the comments why you hate my question so much :D. I think it is a valid problem that others might have as well so I'll keep it.
I'm trying to build a node package.
Environment: vite v6
+ React 18/19
.
Added the configurations at the end of the question.
When I build the project with React 19 it only works on React 19 projects and when I build it with React 18, it works on React 18 projects but not React 19.
There is no breaking change or compatibility issue because I can run the project on both versions in dev environment. The issue arises only when I install it as a npm package on other projects.
I externalized react
and react-dom
.
In the project where the library is installed, I checked the imported React
object used in the library and in the project itself and they both have the same reference (React1 === React2)
but I still get this error when I build with version 19:
Uncaught TypeError: ReactSharedInternals is undefined
By React 18 and trying to run it on React 19 I get the following error:
undefined (reading 'ReactCurrentDispatcher')
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from "path";
export default defineConfig({
plugins: [react()],
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
name: 'app',
formats: ['es', 'umd', 'cjs']
},
rollupOptions: {
external: [
'react',
'react-dom',
'@mui/material',
],
},
sourcemap: false,
minify: false
}
})
package.json
{
"name": "app",
"version": "1.1.17",
"type": "module",
"main": "dist/app.umd.js",
"module": "dist/app.es.js",
"types": "dist/index.d.ts",
"exports": {
"import": "./dist/app.es.js",
"require": "./dist/app.cjs.js"
},
"scripts": {
"dev": "vite",
"build": "vite build && tsc -p tsconfig.build.json --declaration --emitDeclarationOnly --declarationDir dist",
"lint": "eslint .",
"preview": "vite preview"
},
"files": [
"dist"
],
"dependencies": {
},
"devDependencies": {
"@emotion/styled": "^11.13.5",
"@eslint/js": "^9.15.0",
"@mui/material": "^6.1.9",
"@types/node": "^22.10.1",
"@types/react": "^19.1.0",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.8.1",
"eslint": "^9.15.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^15.12.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"typescript": "~5.6.2",
"typescript-eslint": "^8.15.0",
"vite": "^6.2.5"
},
"keywords": [
"react",
"mui",
"snackbar",
"provider",
"hook"
],
"peerDependencies": {
"@emotion/styled": "*",
"@mui/material": "*",
"react": ">=18.*.*",
"react-dom": ">=18.*.*"
},
"sideEffects": false
}
I had to exclude the plugin in the production environment in vite.config.ts
:
plugins: [mode === "development" ? react() : undefined],
and also externalize mui with regex:
external: [
'react',
'react-dom',
/@mui\/material/,
]