vite icon indicating copy to clipboard operation
vite copied to clipboard

Vite >=3.0.1 fails to resolve projects in monorepo

Open lukashroch opened this issue 1 year ago • 6 comments

Describe the bug

Vite 3.0.1 and higher does not seem to resolve projects within the monorepo.

E.g. we got structure:

├─ apps
│  └─ app1
          └─ vite.config.ts
│  └─ app2
└─ packages
   └─ package1
   └─ package2

Since [email protected]., I'm getting the error below:

Error: Cannot find module 'C:\Apps\repo\packages\common\src\types'
Require stack:
- C:\Apps\repo\apps\admin\vite.config.ts
- C:\Apps\repo\node_modules\.pnpm\[email protected][email protected]\node_modules\vite\dist\node\chunks\dep-1513d487.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (C:\Apps\repo\apps\admin\vite.config.ts:117:20)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object._require.extensions.<computed> [as .js] (file:///C:/Apps/repo/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-1513d487.js:62817:24)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)

This was working fine up till [email protected] and breaks in [email protected] and up.

Vite now fails on relative import in vite.config.ts

import { something } from '../../packages/common/src/types';

Is there a more proper way to do this in vite?

Reproduction

https://stackblitz.com/edit/vitejs-vite-wg28sd?file=apps/app/vite.config.ts

cd apps/app
npm install
npm run build

System Info

System:
    OS: Windows 10 10.0.22000
    CPU: (4) x64 Intel(R) Core(TM) i3-8100 CPU @ 3.60GHz
    Memory: 3.85 GB / 15.86 GB
  Binaries:
    Node: 16.13.0 - C:\Program Files\nodejs\node.EXE
    npm: 8.1.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 103.0.5060.114
    Edge: Spartan (44.22000.120.0), Chromium (102.0.1245.44)
    Internet Explorer: 11.0.22000.120

[email protected]

Used Package Manager

pnpm (own project) / npm (stackblitz)

Logs

Error: Cannot find module 'C:\Apps\repo\packages\common\src\types'
Require stack:
- C:\Apps\repo\apps\admin\vite.config.ts
- C:\Apps\repo\node_modules\.pnpm\[email protected][email protected]\node_modules\vite\dist\node\chunks\dep-1513d487.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (C:\Apps\repo\apps\admin\vite.config.ts:117:20)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object._require.extensions.<computed> [as .js] (file:///C:/Apps/repo/node_modules/.pnpm/[email protected][email protected]/node_modules/vite/dist/node/chunks/dep-1513d487.js:62817:24)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)

Validations

lukashroch avatar Jul 18 '22 21:07 lukashroch

Likely a regression from https://github.com/vitejs/vite/pull/9140. We're bundling the Vite config and all the related files, but because the relative imports point to a file from a package that could have it's own node_modules, we can't bundle that file. So what happens is that node is trying to load the file in runtime, which doesn't work as it doesn't handle TS.

The original issue looks like a workaround for https://github.com/vitejs/vite/issues/5370, which doesn't work in the first place. Given this had worked in Vite 3.0.0, maybe it's worth finding a reasonable fix at the meantime, but the better solution overall is to compile the package as JS first.

bluwy avatar Jul 19 '22 13:07 bluwy

@bluwy thanks for your reply, I see that now!

It doesn't make much sense for me to build it in this particular case as it's mostly various shared code being pulled in to apps that take care of the build, whatever if pulled in. Also I had couple of reusable fragments for vite.config.ts in that place as we have multiple vue apps, so wanted to share same pieces. And that's when I started to have issues with vite@>=3.0.1.

For now, I ended up extracting fragments for vite build out of package with package.json / node_modules, which works OK as expected. But if this could be fix, that would be great.

lukashroch avatar Jul 19 '22 17:07 lukashroch

I've been thinking about this and it's quite tricky in general to support this. It's either:

  1. We rewrite the import paths for files in a different package.
  2. Or bundle the file's dependencies.

And both aren't really good choices. The logic for bundling config files is also quite complex now since we had recent issues after Vite 3, and I'm hoping to not touch it anymore.

We might have to intentionally break this in 3.0.1 (even though I hate to break semver), but given that it's a workaround before, and it's only 1 patch away. Maybe that's still acceptable.

bluwy avatar Jul 21 '22 16:07 bluwy

Same thing happens with vitest@^0.17, as it uses the same mechanism for compiling TS config file.

the better solution overall is to compile the package as JS first

What if you don't have a compilation step? I'm using a shared package for defining config like so: https://stackblitz.com/edit/vitejs-vite-esn1xa?file=app%2Fvite.config.ts

It worked with vite@=<3.0.0.

Edit: interestingly enough, when you remove common/package.json, Vite compiles...

KubaJastrz avatar Jul 26 '22 10:07 KubaJastrz

We found a workaround that works for our project, it might work for others (ymmv):

We figured out that we can run Vite through tsx (previously esno). i.e., instead of calling vite we call tsx node_modules/.bin/vite

danielrozenberg avatar Jul 29 '22 17:07 danielrozenberg

We found a workaround that works for our project, it might work for others (ymmv):

We figured out that we can run Vite through tsx (previously esno). i.e., instead of calling vite we call tsx node_modules/.bin/vite

In a project w/ package.json "type": "module", using tsx on the vite's executable fails with:

Click to expand
{
  errors: [
    {
      detail: undefined,
      id: '',
      location: {
        column: 18,
        file: '../node_modules/.bin/vite.js',
        length: 9,
        line: 2,
        lineText: `basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")`,
        namespace: '',
        suggestion: ')'
      },
      notes: [],
      pluginName: '',
      text: 'Expected ")" but found "\\"$(echo \\""'
    }
  ],
  warnings: []
}

o-alexandrov avatar Jul 30 '22 17:07 o-alexandrov

Is there any workaround? I also need to import a common vite.config.ts in monorepo.

Dreamacro avatar Aug 15 '22 02:08 Dreamacro

@Dreamacro a workaround is to move the common config out from a workspace package so it doesn't have it's own node_modules. For example, moving the file to <root-monorepo>/scripts/common-config.js, and import the file via relative paths.

bluwy avatar Aug 15 '22 06:08 bluwy

@bluwy thanks for your reply, I see that now!

It doesn't make much sense for me to build it in this particular case as it's mostly various shared code being pulled in to apps that take care of the build, whatever if pulled in. Also I had couple of reusable fragments for vite.config.ts in that place as we have multiple vue apps, so wanted to share same pieces. And that's when I started to have issues with vite@>=3.0.1.

For now, I ended up extracting fragments for vite build out of package with package.json / node_modules, which works OK as expected. But if this could be fix, that would be great.

But actually its a breaking change.

cutsin avatar Aug 18 '22 10:08 cutsin

This issue makes really hard to use common Vite configs because usually common configs use npm packages. Hope the solution would be found.

For now, here is my workaround: Before:

"scripts": {
    "build": "vite build",
}

After:

"scripts": {
    "build": "ts-node node_modules/vite/bin/vite.js build",
}

edikdeisling avatar Sep 23 '22 06:09 edikdeisling

This issue makes really hard to use common Vite configs because usually common configs use npm packages. Hope the solution would be found.

For now, here is my workaround: Before:

"scripts": {
    "build": "vite build",
}

After:

"scripts": {
    "build": "ts-node node_modules/vite/bin/vite.js build",
}

still got Error: Cannot find module '@shared/xxxx'

any other configs needed?

AkiraX2 avatar Sep 24 '22 04:09 AkiraX2

@maketa521 I think no. One more thing - I use pnpm. Maybe this matters. Also, my node version is v16.16.0 Here is a repo for reproducing it https://github.com/edikdeisling/issue-vite-node-resolution

edikdeisling avatar Sep 24 '22 09:09 edikdeisling