vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
69.01k stars 6.24k forks source link

ENOENT error in dev mode #14493

Open layershifter opened 1 year ago

layershifter commented 1 year ago

Describe the bug

Hello folks πŸ‘‹

I am working on Linaria with @Anber, recently we an issue about the problem in dev mode, https://github.com/callstack/linaria/issues/1246.

To provide context, Linaria performs module evaluation like vite-node as we need to transform styles and for that we should know actual values, for example:

import { colors } from './x'

const style = css` color: ${colors.red}`

For that, we will load files on our side, transform, evaluate and get results. The problem that we faced with Vite is that when dependencies are resolved (https://github.com/callstack/linaria/blob/15fa87a5aab54aec0b8294b81a116aa488e4a417/packages/vite/src/index.ts#L116-L123), they don't exist on a disk yet. For example:

plugin:transform:filename /home/projects/vitejs-vite-xftvql/node_modules/.vite/deps/react.js
plugin:transform:fs.existsSync false

(see Stackblitz repro)

The hack that we made is to call optimizeDeps() forcefully, https://github.com/callstack/linaria/pull/1358. Another solution is to force scan mode:

this._scan = true
const resolvedId = await this.resolve('react', id);
this._scan = false

Both options don't seem correct. Is there API to get path to a module in node_modules via .resolve() or is it possible to read resolved file in this case?

For example, if we will try to use .load(), Vite will be frozen:

  async transform(code, url) {
    const [id] = url.split('?', 1);

    if (url.includes('node_modules')) {
      const resolvedId = await this.resolve('react', id);
      const filename = resolvedId?.id.split('?')[0];

      await this.load(filename)
    }

    return null;
  },

I am not entirely sure that described issue is a bug as it looks like a thing by design, but I would appreciate your input. Thanks.

Reproduction

https://stackblitz.com/edit/vitejs-vite-xftvql

Steps to reproduce

System Info

❯ npx envinfo --system --npmPackages '{vite,@vitejs/*,rollup}' --binaries --browsers

  System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.6.10 - /usr/local/bin/pnpm
  npmPackages:
    @vitejs/plugin-react: ^4.1.0 => 4.1.0 
    vite: ^4.4.9 => 4.4.9

Used Package Manager

npm

Logs

No response

Validations

bluwy commented 1 year ago

this.load() would be the right way to handle it, but currently it's freezing on https://github.com/vitejs/vite/blob/a2e9fb5243874686603814f41410c5b9ba6ac54a/packages/vite/src/node/plugins/optimizedDeps.ts#L48

Our current flow is that we're resolving optimized depedencies eagerly, so you're getting a path that doesn't exist yet. But we're prebundling lazily after every browser requests is settled. We should have some heuristic to prebundle anyway if the waiting has been stucked for X amount of time like in this case, but maybe we're missing something.

kriakiku commented 1 year ago

@layershifter Are there any updates? πŸ‘‰πŸ‘ˆ

layershifter commented 1 year ago

@layershifter Are there any updates? πŸ‘‰πŸ‘ˆ

@kriakiku I think that you tagged a wrong person.

vziatkov commented 1 year ago

are you satisfied answer?

shiro commented 11 months ago

Has there been any new API that can deal with this? :bow:
It makes it impossible for linaria to work in many projects, more deps = higher chance of this happening...

shiro commented 10 months ago

Another option to get it working is to add:

optimizeDeps: {
    disabled: true,
},

to the vite config, however this breaks bundling commonjs dependencies (as they need to be optimized to work with ESM I assume).

shiro commented 9 months ago

So apparently optimizeDeps.disabled is deprecated and will be removed in vite 5.1 (as per the warning being generated), so the workaround will stop working in newer versions.

Is anyone currently looking at this?