-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
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
Pre-bundled dependencies doesn't dedupe imports in external files #3910
Comments
Looking back at this, perhaps the best short-term solution for now is to not prebundle any dependencies/packages that has uncompiled files that contains JS. Basically these items: vite/packages/vite/src/node/optimizer/esbuildDepPlugin.ts Lines 24 to 31 in 69f91a1
These extensions would all technically fail, with un-deduped imports, so it's better to not do any prebundling for libraries that exports these "raw" uncompiled files. Currently for svelte, a heuristic ( However, the above isn't bullet-proof. It's best-effort only and may break depending on how one set up a project. Plus, this works for Svelte only. There's no equivalent heuristic for Vue or marko. So a built-in solution may be the best as proposed above. |
To add on how snowpack/esinstall handles this, it currently bundles external files in the prebundling process as well, leading to one single bundle always. There's of course some issues with this:
Here's also a discussion from snowpack: FredKSchott/snowpack#1808 (comment) |
From some discussion lately in discord and sveltejs/vite-plugin-svelte#125, it looks that auto excluding svelte (and probably marko, solid) libraries would be the way to go, since their compiled outputs are usually only finalised when evaluated in runtime, so they can't really be pre-bundled ahead of time. IssueThe issue now is that as @benmccann pointed out, CJS dependencies used by these excluded libraries (aka transitive CJS deps) wouldn't work in Vite, since Vite doesn't handle CJS in runtime, it expects everything to be in ESM already after prebundling, which is not the case for us. So to fix this, we have two ways:
SolutionAn idea in mind is to work on no1, by altering the prebundling process to address the listed problem above. The altered flow should be like below:
In my mind, if I'm not missing out on anything, this would work nicely with X framework libraries OOTB. There's a small caveat however, that is these X framework libraries need to be in ESM since we exclude them from optimisation. FAQQ: How do we differentiate pure JS libraries vs X framework libraries? |
If anyone has stumbled on this and wants a workaround, exclude the dependency from optimization, e.g. |
There's now an experimental option to prebundle |
When debugging Forgo using `npm link`, Vite's pre-bundling optimization executes the `forgo` module twice ([Vite bug](vitejs/vite#3910), [Svelte bug with workarounds](sveltejs/vite-plugin-svelte#135 (comment))). It doesn't happen when using the package from npm. This results in different code paths holding references to two different `Fragment` symbols, causing renders to fail because the two symbols aren't comparable using `===`. Using `Symbol.for()` makes all symbols named `FORGO_FRAGMENT` comparable, no matter where they come from. Alternatively, there's a workaround to have Vite disable pre-bundling optimizations for `forgo`, but this patch makes that unnecessary.
When debugging Forgo using `npm link`, Vite's pre-bundling optimization executes the `forgo` module twice ([Vite bug](vitejs/vite#3910), [Svelte bug with workarounds](sveltejs/vite-plugin-svelte#135 (comment))). It doesn't happen when using the package from npm. This results in different code paths holding references to two different `Fragment` symbols, causing renders to fail because the two symbols aren't comparable using `===`. Using `Symbol.for()` makes all symbols named `FORGO_FRAGMENT` comparable, no matter where they come from. Alternatively, there's a workaround to have Vite disable pre-bundling optimizations for `forgo`, but this patch makes that unnecessary.
Hi, not sure this is related but I have a similar issue. I’m using React 17 and use lazy-loaded routes. The issue is happening with a font awesome SVG icon. import { faCircleQuestion } from '@fortawesome/free-solid-svg-icons/faCircleQuestion'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
// ...
<FontAwesomeIcon icon={faCircleQuestion} /> If I first go to route A, the icon works. If I first go to route B, the icon doesn’t work. But, if I first go to route A, then route B, the icon works! I looked at the code generated after building the app, and I can see this in route B’s JS files: /* file1.js */
// ...
var le = {};
// ...
export {le as f};
/* file2.js */
import {f as ma} from "./file1.js";
// ...
children: c(Xn, {
icon: ma.faCircleQuestion
}) As you can see, I tried to add /* unbuilded code */
import { definition as faCircleQuestion } from '@fortawesome/free-solid-svg-icons/faCircleQuestion'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
// ...
/* file1.js */
// ...
var N = {};
(function(e) {
Object.defineProperty(e, "__esModule", {
value: !0
});
var n = "fas"
, a = "circle-question"
, i = 512
, r = 512
, t = [62108, "question-circle"]
, o = "f059"
, l = "M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 400c-18 0-32-14-32-32s13.1-32 32-32c17.1 0 32 14 32 32S273.1 400 256 400zM325.1 258L280 286V288c0 13-11 24-24 24S232 301 232 288V272c0-8 4-16 12-21l57-34C308 213 312 206 312 198C312 186 301.1 176 289.1 176h-51.1C225.1 176 216 186 216 198c0 13-11 24-24 24s-24-11-24-24C168 159 199 128 237.1 128h51.1C329 128 360 159 360 198C360 222 347 245 325.1 258z";
e.definition = {
prefix: n,
iconName: a,
icon: [i, r, t, o, l]
},
e.faCircleQuestion = e.definition,
e.prefix = n,
e.iconName = a,
e.width = i,
e.height = r,
e.ligatures = t,
e.unicode = o,
e.svgPathData = l,
e.aliases = t
}
)(N);
// ...
export {N as f};
/* file2.js */
// content unchanged This way, it works even if I first load route B, and still works when I first load route A. I might add that this is not happening with development server, only when builded and served by a simple nginx server. EDIT: I also was able to make it work by updating both routes code like this: import faCircleQuestion from '@fortawesome/free-solid-svg-icons/faCircleQuestion'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
// ...
<FontAwesomeIcon icon={faCircleQuestion.faCircleQuestion} /> |
Is this problem solved? I have a similar problem The vite dev environment is packaged with two versions, which causes the configuration to be loaded separately, and the instance cannot be shared.
and
I have this problem in |
@ZengTianShengZ this isn't fixed yet, but you can workaround by adding the dependency to |
Already spent a few weeks on my project fighting that bug. We are using vite + pnpm and a lot of third-party deps in our internal library (in our artefacts repo), so the list of the includes is already like this:
The developers are super tired of adding each dependency one by one including each icon! And the problem is that you are finding out that the dependency is missing only after you pull the latest version of the lib from the artifacts report and trying to use it 😞 |
I'm not sure this issue is related to what you're getting. You can check https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies if you're working in a monorepo. Otherwise for your case in particular, perhaps you can try |
Arrow-js uses brittle `instanceof` checks throughout the code base. These fail unless the library instance that produced the object matches exactly the same instance the vectordb is using. At a minimum, this means that a user using arrow version 15 (or any version that doesn't match exactly the version that vectordb is using) will get strange errors when they try and use vectordb. However, there are even cases where the versions can be perfectly identical, and the instanceof check still fails. One such example is when using `vite` (e.g. vitejs/vite#3910) This PR solves the problem in a rather brute force, but workable, fashion. If we encounter a schema that does not pass the `instanceof` check then we will attempt to sanitize that schema by traversing the object and, if it has all the correct properties, constructing an appropriate `Schema` instance via deep cloning.
Arrow-js uses brittle `instanceof` checks throughout the code base. These fail unless the library instance that produced the object matches exactly the same instance the vectordb is using. At a minimum, this means that a user using arrow version 15 (or any version that doesn't match exactly the version that vectordb is using) will get strange errors when they try and use vectordb. However, there are even cases where the versions can be perfectly identical, and the instanceof check still fails. One such example is when using `vite` (e.g. vitejs/vite#3910) This PR solves the problem in a rather brute force, but workable, fashion. If we encounter a schema that does not pass the `instanceof` check then we will attempt to sanitize that schema by traversing the object and, if it has all the correct properties, constructing an appropriate `Schema` instance via deep cloning.
Arrow-js uses brittle `instanceof` checks throughout the code base. These fail unless the library instance that produced the object matches exactly the same instance the vectordb is using. At a minimum, this means that a user using arrow version 15 (or any version that doesn't match exactly the version that vectordb is using) will get strange errors when they try and use vectordb. However, there are even cases where the versions can be perfectly identical, and the instanceof check still fails. One such example is when using `vite` (e.g. vitejs/vite#3910) This PR solves the problem in a rather brute force, but workable, fashion. If we encounter a schema that does not pass the `instanceof` check then we will attempt to sanitize that schema by traversing the object and, if it has all the correct properties, constructing an appropriate `Schema` instance via deep cloning.
Arrow-js uses brittle `instanceof` checks throughout the code base. These fail unless the library instance that produced the object matches exactly the same instance the vectordb is using. At a minimum, this means that a user using arrow version 15 (or any version that doesn't match exactly the version that vectordb is using) will get strange errors when they try and use vectordb. However, there are even cases where the versions can be perfectly identical, and the instanceof check still fails. One such example is when using `vite` (e.g. vitejs/vite#3910) This PR solves the problem in a rather brute force, but workable, fashion. If we encounter a schema that does not pass the `instanceof` check then we will attempt to sanitize that schema by traversing the object and, if it has all the correct properties, constructing an appropriate `Schema` instance via deep cloning.
Describe the bug
When Vite pre-bundles a dependency, if the dependency's entrypoint file imports an external file (e.g.
Foo.svelte
), imports in that external file aren't deduped.For example, given
foo-library
innode_modules
with these files:Vite will prebundle
foo-library
as.vite/foo-library.js
:^ This is the problem,
Component.vue
will importbar
from it's relative'./shared.js
file, but.vite/foo-library.js
has its ownbar
reference! This causes a lot of hard to catch bugs, especially for the Svelte ecosystem.Reproduction
https://github.com/bluwy/vite-svelte-dedupe
(It's a Svelte-specific repro but the general issue applies)
System Info
Output of
npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers
:Used package manager: pnpm
Before submitting the issue, please make sure you do the following
The text was updated successfully, but these errors were encountered: