Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

预览模式中element-ui el-table jsx写法不显示 #12957

Closed
7 tasks done
damian-64 opened this issue Apr 23, 2023 · 11 comments
Closed
7 tasks done

预览模式中element-ui el-table jsx写法不显示 #12957

damian-64 opened this issue Apr 23, 2023 · 11 comments

Comments

@damian-64
Copy link

damian-64 commented Apr 23, 2023

Describe the bug

element-ui el-table jsx在 vite4.2.x 预览中是正常, 在vite4.3.x 开发中正常显示,在预览中不显示

Reproduction

https://github.com/satrong/vite-4.3-element-ui

Steps to reproduce

No response

System Info

win11,node18,vue2.7

Used Package Manager

npm

Logs

No response

Validations

@github-actions
Copy link

Hello @damian-64. Please provide a minimal reproduction using a GitHub repository or StackBlitz. Issues marked with need reproduction will be closed if they have no activity within 3 days.

@satrong
Copy link

satrong commented Apr 24, 2023

Here is minimal reproduction https://github.com/satrong/vite-4.3-element-ui

Works fine in development mode (pnpm dev) but not in production (pnpm build && pnpm preview).

@hankaibo
Copy link

Here is minimal reproduction https://github.com/satrong/vite-4.3-element-ui

Works fine in development mode (pnpm dev) but not in production (pnpm build && pnpm preview).

me too.
but, I meet it is

RollupError: Could not resolve "./src/button" from "node_modules/.pnpm/[email protected][email protected]/node_modules/element-ui/packages/button/index.js"

@sapphi-red
Copy link
Member

I dug this one down and found that this just happened to work. You are facing a dual package hazard.
The reason why the dual package hazard happens is:

  • App.vue -> vue: uses "import" so it resolves to ESM version
  • element-ui -> vue: uses "require". resolves to CJS version

related: #11389

Why does this work with npm + Vite 4.3?

It seems there's a bug in Vite.
First, getResolvedCache and setResolvedCache mixes the ESM resolved result and CJS resolved result. Even if the id and the targetWeb is same, the resolved result can be different by isRequire.
Second, rpdCache (resolvePackageData cache) returns multiple instances for the same directory when the package is a symlink. So for npm all instances are shared, but for pnpm it's not. I guess we have to add the realpathed package path to the cache.

/cc @bluwy

Why does this work during dev?

It seems the dep optimizer has a bug. It's mixing ESM version and CJS version.

@bluwy
Copy link
Member

bluwy commented May 16, 2023

First, getResolvedCache and setResolvedCache mixes the ESM resolved result and CJS resolved result. Even if the id and the targetWeb is same, the resolved result can be different by isRequire.

Yeah that has bitten me in the optimizer before. I'm not sure why it only comes out now as we had the getResolvedCache and setResolvedCache pattern long ago.

Second, rpdCache (resolvePackageData cache) returns multiple instances for the same directory when the package is a symlink. So for npm all instances are shared, but for pnpm it's not. I guess we have to add the realpathed package path to the cache.

I don't understand this part, we do realpath the package path in the cache, and rpdCache includes preserveSymlinks as the cache key. Perhaps it's an issue with deduping?

@sapphi-red
Copy link
Member

I don't understand this part, we do realpath the package path in the cache, and rpdCache includes preserveSymlinks as the cache key. Perhaps it's an issue with deduping?

For example, if we had two modules A and B importing vite:

  • A: /foo/index.js
  • B: /foo/node_modules/dep/index.js (in pnpm case, it's a symlink to /foo/node_modules/.pnpm/[email protected]/node_modules/dep/index.js)

resolving vite from A

  1. getRpdCache(basedir: '/foo', pkgName: 'vite') -> returns undefined
  2. pkg: '/foo/node_modules/vite/package.json'
  3. fs.existsSync(pkg) -> true
  4. pkgPath: '/foo/node_modules/.pnpm/[email protected]/node_modules/vite/package.json'
  5. setRpdCache(basedir: '/foo', pkgName: 'vite')

resolving vite from B in npm case

  1. getRpdCache(basedir: '/foo/node_modules/dep', pkgName: 'vite') -> returns undefined
  2. pkg: '/foo/node_modules/dep/node_modules/vite/package.json'
  3. fs.existsSync(pkg) -> false
  4. getRpdCache(basedir: '/foo/node_modules', pkgName: 'vite') -> returns undefined
  5. pkg: '/foo/node_modules/node_modules/vite/package.json'
  6. fs.existsSync(pkg) -> false
  7. getRpdCache(basedir: '/foo', pkgName: 'vite') -> returns cached

In 7, the same instance with A is returned. So if setResolvedCache ran when resolving A, it used with getResolvedCache when resolving B.

resolving vite from B in pnpm case

  1. getRpdCache(basedir: '/foo/node_modules/.pnpm/[email protected]/node_modules/dep', pkgName: 'vite') -> returns undefined
  2. pkg: '/foo/node_modules/.pnpm/[email protected]/node_modules/dep/node_modules/vite/package.json'
  3. fs.existsSync(pkg) -> false
  4. getRpdCache(basedir: '/foo/node_modules/.pnpm/[email protected]/node_modules', pkgName: 'vite') -> returns undefined
  5. pkg: '/foo/node_modules/.pnpm/[email protected]/node_modules/node_modules/vite/package.json'
  6. fs.existsSync(pkg) -> false
  7. getRpdCache(basedir: '/foo/node_modules/.pnpm/[email protected]', pkgName: 'vite') -> returns undefined
  8. pkg: '/foo/node_modules/.pnpm/[email protected]/node_modules/vite/package.json'
  9. fs.existsSync(pkg) -> true
  10. pkgPath: '/foo/node_modules/.pnpm/[email protected]/node_modules/vite/package.json'
  11. setRpdCache(basedir: '/foo/node_modules/.pnpm/[email protected]', pkgName: 'vite')

In 11, a different instance is set. So the resolvedCache is not shared. Note that even if a same path is passed to loadPackageData, a different instance will be returned as we don't have any deduping/caching mechanism inside that function.

@bluwy
Copy link
Member

bluwy commented May 17, 2023

Thanks for the explanation! I thought it was the module instance duplicated, but seems like you're referring to the PackageData being duplicated. Sharing the same PackageData for the same realpath-ed `package.json path does seem to fix it.

I don't remember Vite 4.2 having this dedupe mechanism though, but likely in multiple 4.3 refactors that this surfaced up. I'd be fine to go with the shared PackageData trick if it means preventing the regression.

In the future, I hope to remove the getResolvedCache and setResolvedCache caching altogether though, resolving is tied to a lot of options and not just the package.json (so technically it would regress again? 🤔). I've discussed with patak before that the PackageCache being public API is making it hard to refactor this, and we're planning to make it private in the next major.

@GGBeng1
Copy link

GGBeng1 commented Jun 30, 2023

这个问题能够在最新的[email protected]的正式版本修复吗? 😄

@GGBeng1
Copy link

GGBeng1 commented Aug 11, 2023

这个问题能够在最新的[email protected]的正式版本修复吗? 😄

4.4.9了( 流泪

@chenweiyi
Copy link

指定 alias 中的 vue 可以生效

resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src'),
        'vue': 'vue/dist/vue.esm.js'  // 这里配置这个可以生效
      },
      extensions: [
        '.js',
        '.json',
        '.vue'
      ]
}

@sapphi-red
Copy link
Member

Checking this issue once again, it seems this is caused by plugin-vue2's code.
This line is updating config.resolve.alias but at that time the alias plugin is already created and this change does not effect it.
https://github.com/vitejs/vite-plugin-vue2/blob/03a504bc5ec3b63ab502ccccc42973ee0eac542a/src/index.ts#L103-L108
Closing as this needs to be fixed on the plugin-vue2 side.

@github-actions github-actions bot locked and limited conversation to collaborators Oct 26, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants