I have a monorepo project using turborepo
. I was using yarn version 4 and everything was working perfectly fine but then I had the brilliant idea of changing from yarn to pnpm since it was recommended for monorepo (at least from what I've read).
I deleted all yarn references and changed it to pnpm, ran pnpm import
, deleted node_modules
, and ran pnpm install
.
When I try to build one project that uses react and vite, I always get "Rollup failed to resolve import".
For example, I have zustand
and then it says it failed to resolve import use-sync-external-store/shim/with-selector.js.
tanstack/react-query
asked for @tanstack/query-core
and @tanstack/query-persist-client-core
.
I tried adding them to the external rollup property in the vite.config
file, but I have added 59 different packages so far.
Whenever I run, it says it's missing a peer dependency, I add this dependency in the external, run build again, and it complains about another dependency, I add it to external, build again, and then I keep in this dependency hell.
I don't know how to fix it.
I have this in my .pnpm
link-workspace-packages=true
and this in my pnpm-workspace.yaml
packages:
- 'apps/*'
- 'shared/*'
This is my complete vite.config.mts file
export default defineConfig(({ mode }) => ({
plugins: [
react(),
svgr(),
],
resolve: {
preserveSymlinks: true,
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
build: {
rollupOptions: {
external: [
'clsx',
'use-sync-external-store/with-selector.js',
'@floating-ui/react-dom-interactions',
'htm/react',
'@tanstack/query-core',
'@tanstack/query-persist-client-core',
'react-router',
'@remix-run/router',
'immer',
'@babel/runtime/helpers/esm/classCallCheck',
'@babel/runtime/helpers/esm/createClass',
'@babel/runtime/helpers/esm/objectWithoutPropertiesLoose',
'reselect',
'redux-thunk',
'react-merge-refs',
'@tanstack/query-devtools',
'html-parse-stringify',
'@progress/kendo-charts',
'@babel/runtime/helpers/esm/extends',
'@babel/runtime/helpers/esm/inheritsLoose',
'@babel/runtime/helpers/esm/toConsumableArray',
'@babel/runtime/helpers/esm/assertThisInitialized',
'dom-helpers/addClass',
'dom-helpers/removeClass',
'@babel/runtime/helpers/esm/inherits',
'@babel/runtime/helpers/esm/possibleConstructorReturn',
'@babel/runtime/helpers/esm/getPrototypeOf',
'@babel/runtime/helpers/esm/defineProperty',
'invariant',
'@babel/runtime/helpers/esm/slicedToArray',
'substyle',
'@progress/kendo-draggable-common',
'pdfjs-dist',
'make-event-props',
'make-cancellable-promise',
'tiny-invariant',
'warning',
'dequal',
'merge-refs',
'use-sync-external-store/shim/with-selector.js',
'tslib',
'@progress/pako-esm',
'js-cookie',
'nano-css',
'nano-css/addon/cssom',
'nano-css/addon/vcssom',
'nano-css/addon/vcssom/cssToTree',
'copy-to-clipboard',
'screenfull',
'set-harmonic-interval',
'throttle-debounce',
'react-universal-interface',
'fast-shallow-equal',
'ts-easing',
'@xobotyi/scrollbar-width',
'fast-deep-equal/react',
'@kurkle/color',
'@zxing/library',
'@progress/jszip-esm',
],
},
},
esbuild: {
drop: ['console', 'debugger'],
},
define: {
APP_VERSION: JSON.stringify(process.env.npm_package_version),
},
}));
Taking zustand as an example it is only installed in the app/app1 folder (I'm using app1 for anonymity) This is my root package.json
{
"name": "monorepo",
"private": true,
"scripts": {
"build": "pnpm install && turbo build",
// removed for simplicity
},
"devDependencies": {
"husky": "^9.0.11",
"prettier": "^3.3.1",
"turbo": "^2.0.11",
"typescript": "^5.5.2"
},
"packageManager": "pnpm@9.7.1",
"engines": {
"node": ">=20"
}
}
and this is my app1 package.json (I kept only some relevant packages that I think makes sense)
{
"name": "app1",
"private": true,
"dependencies": {
"@tanstack/react-query": "^5.40.1",
"@tanstack/react-query-devtools": "^5.40.1",
"@tanstack/react-query-persist-client": "^5.49.2",
"idb-keyval": "^6.2.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"zustand": "^4.5.4"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build --outDir build",
"preview": "vite preview --outDir build --port=3000",
"test": "vitest"
},
"devDependencies": {
"@types/node": "^20.14.7",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"typescript": "^5.5.2",
"vite": "^5.4.1",
"vitest": "^1.6.0",
"webpack": "^5.90.3"
},
"jest": {
"moduleNameMapper": {
"axios": "axios/dist/node/axios.cjs"
}
},
"overrides": {
"redux-persist": {
"redux": "^5.0.0"
},
"redux-state-sync": {
"redux": "^5.0.0"
}
}
}
Adding this to the .npmrc solved my problem:
shamefully-hoist=true
I think it is because I must use preserveSymlinks: true
due to the Jenkins environment we use to build.
I found it because in the documentation it says the node-linker
should be set to hoisted when:
If you are running Node.js with the --preserve-symlinks flag.
node-linker