Optimizer behaviour change leading to errors
Describe the bug
The changes in this PR have created issues for users of @cloudflare/vite-plugin. Upgrading to vite@^7.1.3 is leading to frequent occurrences of Error: There is a new version of the pre-bundle for ... errors.
Reproduction
https://github.com/jamesopstad/optimize-deps-repro
Steps to reproduce
Run pnpm i followed by pnpm dev. Every browser refresh will trigger the error.
Note that I have patched TanStack Start so that dependencies are not discovered ahead of time. This makes the issue more obvious. If the Vite version is switch from 7.1.3 to 7.1.2 then an error occurs on the first load but not subsequent loads. This is the expected behaviour.
System Info
System:
OS: macOS 15.6.1
CPU: (12) arm64 Apple M3 Pro
Memory: 1.12 GB / 36.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.2.0 - ~/.nvm/versions/node/v24.2.0/bin/node
Yarn: 1.22.22 - ~/.nvm/versions/node/v24.2.0/bin/yarn
npm: 11.3.0 - ~/.nvm/versions/node/v24.2.0/bin/npm
pnpm: 10.15.1 - ~/.nvm/versions/node/v24.2.0/bin/pnpm
Browsers:
Chrome: 140.0.7339.208
Safari: 18.6
Used Package Manager
pnpm
Logs
Error: There is a new version of the pre-bundle for ...
Validations
- [x] Follow our Code of Conduct
- [x] Read the Contributing Guidelines.
- [x] Read the docs.
- [x] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [x] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [x] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [x] The provided reproduction is a minimal reproducible example of the bug.
The error itself seems to be a valid one. This error prevents the same module to be loaded more than once so that a single module has a single reference.
We can add a flag to opt-out that check, which means you may have multiple instances of a same module, as a temporary workaround. The real fix would be to solve https://github.com/vitejs/vite/issues/19323.
Retrying the import doesn't work here because that would not affect the code that is already executed.
OK. So, as I understand it, the bug that was fixed in Vite was masking incorrect behaviour before. Would adding our own retry mechanism around runner.import (like you have here) help in this case?
I think in the short term we probably do need some way to opt in to the previous behaviour unless there's another quick fix. optimizeDeps on the server has always been quite problematic and I think the longer term solution for our use case is Rolldown full-bundle mode. I'm hopeful that it will be a much better fit for bundling server code in development.
Would adding our own retry mechanism around
runner.import(like you have here) help in this case?
If there's only one entrypoint (i.e. only one value is passed to runner.import()) and there's no try-catch that modifies the throwed value around a dynamic import, I guess it would help.
I'm stuck on 7.1.2 due to this issue working with cloudflare-vite.
Here's a repro. https://github.com/austinm911/zero-starter/tree/vite-pre-bundle-repro?tab=readme-ov-file
Would adding our own retry mechanism around
runner.import(like you have here) help in this case?If there's only one entrypoint (i.e. only one value is passed to
runner.import()) and there's notry-catchthat modifies the throwed value around a dynamic import, I guess it would help.
I haven't had any luck with this approach but I also think it would be good to find a solution that solves some of the other issues with optimizeDeps if possible.
What do you think about adding an option to optimizeDeps so that it doesn't create shared chunks and instead bundles each dependency separately? I think you mentioned this as one possibility when we spoke @sapphi-red. By default a dependency's sub-dependencies would be bundled with it but optimizeDeps.include could be used to force a sub-dependency into its own chunk so that it can be shared. This could be used for libraries like React where it's important not to have multiple copies. The advantage of this approach is that, when new dependencies are discovered, it's purely additive and they don't invalidate those that have already been optimised.
What do you think about adding an option to
optimizeDepsso that it doesn't create shared chunks and instead bundles each dependency separately?
I think it can work. But when the user encounters a package that requires a single copy, I think it would be harder to debug and find out that they need to set an option. The current "a new version of the pre-bundle ..." error is unique enough that users can find out the cause and can add optimizeDeps.include.
But when the user encounters a package that requires a single copy, I think it would be harder to debug and find out that they need to set an option.
I agree this is a concern.
The current "a new version of the pre-bundle ..." error is unique enough that users can find out the cause and can add
optimizeDeps.include.
I don't think most users would know to update optimizeDeps.include when they see "a new version of the pre-bundle ..." (especially as they need to do it at the environment level). But also, in many cases, doing so doesn't resolve the issue. In the repro @austinm911 shared above, for example, the error message says that there is a new version of @rocicorp_zero_react but this is triggered by better-auth/react being discovered during request handling. In this case, better-auth/react wasn't discovered during the initial scan because it was tree shaken by ESBuild.
The current "a new version of the pre-bundle ..." error is unique enough that users can find out the cause and can add
optimizeDeps.include.I don't think most users would know to update
optimizeDeps.includewhen they see "a new version of the pre-bundle ..." (especially as they need to do it at the environment level).
I mean we can improve the error message to include which dependency needs to be added to which option.