vitejs / vite

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

Regression from 5.1.6 -> 5.2.0+ regarding handling of npm package aliases #17633

Closed tb-viktor closed 3 weeks ago

tb-viktor commented 3 months ago

Describe the bug

Hey everyone,

We're experiencing a regression with how npm package aliases seem to be handled by Vite in versions after 5.1.6. We waited for a while thinking that it's a bug that would be resolved soon, but even with the latest version of Vite this still happens, so I am opening this issue about it.

In our product we have a setup where we are temporarily using two three versions via npm package aliases, since we have to use a loader from a newer version to load 3DM files:

"three": "^0.160.1",
"three165": "npm:three@^0.165.0",

And the resulting code:

import { ... } from 'three';
import { Rhino3dmLoader } from 'three165/examples/jsm/loaders/3DMLoader';

This used to work fine in 5.1.6, and the loader would correctly load and render the file, but since upgrading to 5.2.0+ something goes wrong and the model does not load correctly anymore. I've made a minimal reproduction on stackblitz using the react-ts starter. The reproduction steps are also provided.

Initially this only happened for us with production bundles (npm run build -> npm run preview), but on stackblitz, it seems to also happen during development. On the plus side, this makes debugging easier.

Any idea what is going wrong?

Reproduction

https://stackblitz.com/edit/vitejs-vite-y54j6h?file=package.json

Steps to reproduce

  1. Load the reproduction link: https://stackblitz.com/edit/vitejs-vite-y54j6h?file=package.json
  2. Use the file input to upload the sample 3dm file: https://raw.githubusercontent.com/mrdoob/three.js/master/examples/models/3dm/Rhino_Logo.3dm
  3. The rhino logo will show up next to the two boxes.
  4. Stop the dev server and in the terminal write: npm install vite@5.2.0, then npm run dev
  5. Use the file input again and select the rhino logo.
  6. The boxes will render, but the rhino logo will not show up.

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (8) x64 Intel(R) Core(TM) i5-1035G7 CPU @ 1.20GHz
    Memory: 5.75 GB / 15.60 GB
  Binaries:
    Node: 20.15.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.8.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (126.0.2592.81)
    Internet Explorer: 11.0.19041.4355
  npmPackages:
    @vitejs/plugin-react: ^4.3.1 => 4.3.1
    vite: ^5.3.3 => 5.3.3

Used Package Manager

npm

Logs

No response

Validations

stackblitz[bot] commented 3 months ago

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

rphlmr commented 1 month ago

I faced the same issue all day long for a production build (was ok on dev). I think it’s because of some chunk mixing.

I found a solution: make the aliased dependency its own chunk

    rollupOptions: {
      output: {
        manualChunks: (id) => {
          if (id.includes("three165")) {
            return "three165";
          }
        },
      },
    },
sapphi-red commented 3 weeks ago

This was caused by #16068. The behavior change is expected.

This file imports three.js by three. https://github.com/mrdoob/three.js/blob/5a8328736ca7207f386254f88ddb795d396877db/examples/jsm/loaders/3DMLoader.js#L27 Before #16068, that resolved to node_modules/three because node_modules/three is a phantom dependency of node_module/three165. If you use a package manager that avoids the phantom dependency problem like pnpm, you can see that it won't work. After #16068, three is now treated as a self-referencing import and resolves to node_module/three165. That causes two three.js to be served / bundled.

For your case, adding resolve.alias like below should work.

import path from 'node:path'
import url from 'node:url'

const _dirname = path.dirname(url.fileURLToPath(import.meta.url))

export default defineConfig({
    resolve: {
        alias: {
            'three': path.resolve(_dirname, './node_modules/three/build/three.module.js')
        }
    },
})

Closing as this is not a bug.