-
-
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
fix: don't store temporary vite config file in node_modules
if deno
#18823
fix: don't store temporary vite config file in node_modules
if deno
#18823
Conversation
packages/vite/src/node/config.ts
Outdated
@@ -1859,18 +1859,20 @@ async function loadConfigFromBundledFile( | |||
// write it to disk, load it with native Node ESM, then delete the file. | |||
if (isESM) { | |||
const nodeModulesDir = findNearestNodeModules(path.dirname(fileName)) | |||
if (nodeModulesDir) { | |||
const isDeno = !!(globalThis as any).Deno |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that ideally this condition should be checking if the env is Node.js or not but there doesn't seem to be a way to reliably detect that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is special behavior on the Deno side and correct to branch on Deno.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, assuming that arbitrary files (not npm packages) placed in node_modules/
will work regardless of the runtime is quite a leap compared to storing files meant to be consumed in the browser in node_modules/.vite
.
I believe that placing application files under node_modules/
and executing them with a runtime is not something that a runtime (or package manager) would anticipate. Therefore, I would argue that the current design relies on the specific behavior of Node.js and should not be assumed to work universally across all runtimes.
(I understand it's not my call and it's definitely out of scope but just wanted to share my thoughts 💭)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is just a matter of perspective. The reason Vite works with deno is because deno is fairly compatible enough with Node, not because Vite tries to support all existing runtimes (not saying deno isn't supported, it's just how it currently works). From that point of view, deno lacks Node.js compatibility here, and Vite applies a patch for deno (that said, I personally think that behaving differently in node_modules is a valid choice on deno's side).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree, it is a matter of perspective but I was just curious if this fairly uncommon approach (even from node's standards) to store modules that are executed by the host runtime in node_modules/
is worth the benefits compared to the potential breaks that it may introduce for other runtimes.
Anyway, thanks for elaborating 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unfortunate that we cannot use node_modules
to write the temporary file. I don't come up with other ways. I think we should go with this one.
packages/vite/src/node/config.ts
Outdated
@@ -1859,18 +1859,20 @@ async function loadConfigFromBundledFile( | |||
// write it to disk, load it with native Node ESM, then delete the file. | |||
if (isESM) { | |||
const nodeModulesDir = findNearestNodeModules(path.dirname(fileName)) | |||
if (nodeModulesDir) { | |||
const isDeno = !!(globalThis as any).Deno |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is special behavior on the Deno side and correct to branch on Deno.
@@ -1859,18 +1859,20 @@ async function loadConfigFromBundledFile( | |||
// write it to disk, load it with native Node ESM, then delete the file. | |||
if (isESM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const hasNpmPrefixExternalImport = Object.values(result.metafile.outputs)
.flatMap((output) => output.imports)
.filter((imp) => imp.external && imp.path.startsWith('npm:'))
Does passing this value from bundleConfigFile
and only avoid writing to node_modules
in that case work? If I understand correctly, the problem only happens if the config file has an import with npm:
prefix.
If you have a code like below, it won't work. But this is already not supported, so it should be fine.
const dynImport = (str: string) => import(str)
dynImport('npm:foo')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, the problem only happens if the config file has an import with npm: prefix.
Yes, you're right! Here's a break down of what's going to happen for clarity.
- Vite removes the
npm:
prefix from import statements - bundled file is executed with Deno
- Deno's module resolution expects an
npm:
prefix when we want to do something likeimport { defineConfig } from 'vite';
- However since this bundled file is placed in
node_modules/
, Deno will consider the file as an Node.js compatible module and resolve import statements accordingly - import works!
So your solution should work, but I think it make thing too unpredictable and fragile because it's like trying to implement a transformation layer that voids Deno's behavior difference for modules inside/outside of node_modules/
Since the bundled file is going to be executed by Deno not Node, I'd say that keeping the import statements as-is is a better solution.
@sapphi-red thanks for the prompt review! I've addressed your comments! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
| datasource | package | from | to | | ---------- | ------- | ----- | ----- | | npm | vite | 6.0.1 | 6.0.2 | ## [v6.0.2](https://github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small602-2024-12-02-small) - chore: run typecheck in unit tests ([#18858](vitejs/vite#18858)) ([49f20bb](vitejs/vite@49f20bb)), closes [#18858](vitejs/vite#18858) - chore: update broken links in changelog ([#18802](vitejs/vite#18802)) ([cb754f8](vitejs/vite@cb754f8)), closes [#18802](vitejs/vite#18802) - chore: update broken links in changelog ([#18804](vitejs/vite#18804)) ([47ec49f](vitejs/vite@47ec49f)), closes [#18804](vitejs/vite#18804) - fix: don't store temporary vite config file in `node_modules` if deno ([#18823](vitejs/vite#18823)) ([a20267b](vitejs/vite@a20267b)), closes [#18823](vitejs/vite#18823) - fix(css): referencing aliased svg asset with lightningcss enabled errored ([#18819](vitejs/vite#18819)) ([ae68958](vitejs/vite@ae68958)), closes [#18819](vitejs/vite#18819) - fix(manifest): use `style.css` as a key for the style file for `cssCodesplit: false` ([#18820](vitejs/vite#18820)) ([ec51115](vitejs/vite@ec51115)), closes [#18820](vitejs/vite#18820) - fix(optimizer): resolve all promises when cancelled ([#18826](vitejs/vite#18826)) ([d6e6194](vitejs/vite@d6e6194)), closes [#18826](vitejs/vite#18826) - fix(resolve): don't set builtinModules to `external` by default ([#18821](vitejs/vite#18821)) ([2250ffa](vitejs/vite@2250ffa)), closes [#18821](vitejs/vite#18821) - fix(ssr): set `ssr.target: 'webworker'` defaults as fallback ([#18827](vitejs/vite#18827)) ([b39e696](vitejs/vite@b39e696)), closes [#18827](vitejs/vite#18827) - feat(css): format lightningcss error ([#18818](vitejs/vite#18818)) ([dac7992](vitejs/vite@dac7992)), closes [#18818](vitejs/vite#18818) - refactor: make properties of ResolvedServerOptions and ResolvedPreviewOptions required ([#18796](vitejs/vite#18796)) ([51a5569](vitejs/vite@51a5569)), closes [#18796](vitejs/vite#18796)
Description
fixes #18822
This fixes an issue where Vite v6 does not work on Deno when import statements with the specifier
npm:
is used in the config file.Vite will create a bundled version of
vite.config.ts
undernode_modules/.vite-temp
ifnode_modules/
exits. Import statements like the following will be kept in the generated output.When this generated file is
import()
ed by Vite running on Deno, Deno will throw an errorTypeError: [ERR_UNSUPPORTED_ESM_URL_SCHEME]
. This is because Deno assumes that modules undernode_modules/
is a valid file for executing with Node.js and considers thenpm:
prefix invalid.This patch will check if the the environment is Deno and will prevent from storing the temp file under
node_modules/
if its Deno.