-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
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
Support for moduleInfo.meta in resolveId hook still not equivalent in vite dev and vite build #6766
Comments
It's your own bug :) The |
You're misreading the code. Did you try the minimal reproducible repo I constructed and attached? Here is a change dversion of import path from 'path';
export default {
plugins: [
{
enforce: 'pre',
async resolveId(id) {
let [file, query] = id.split('?');
const probe = query && query.match(/xoption=([^&]+)/)
const x = probe && Number(probe[1])
if (x) {
const realone = path.resolve(file);
console.log('IS THIS FILE REAL ON THE FS?', realone);
return {id: realone, meta: {x}}
}
},
async transform(blob, id) {
const x = this.getModuleInfo(id)?.meta?.x
if (x) return `window.THE_X = ${x}\n` + blob;
}
}
]
} logs
Also, why would this work with |
Hi @aleclarson. I hope you can appreciate this report again. I've dug down to the root of the problem. Here is a possible fix (but not the cleanest one, I'll present that cleaner one later as a PR). The comments should hint as to what goes wrong and how this fixes it. diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts
index 953304e0..4a5c5281 100644
--- a/packages/vite/src/node/plugins/importAnalysis.ts
+++ b/packages/vite/src/node/plugins/importAnalysis.ts
@@ -178,6 +178,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
url: string,
pos: number
): Promise<[string, string]> => {
+ const uncleanUrl = url;
if (base !== '/' && url.startsWith(base)) {
url = url.replace(base, '/')
}
@@ -259,7 +260,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
// its last updated timestamp to force the browser to fetch the most
// up-to-date version of this module.
try {
- const depModule = await moduleGraph.ensureEntryFromUrl(url, ssr)
+ // make sure we feed the original "unclean" URL to ensureEntryFromUrl
+ // so as to call the very same user plugins as in build mode.
+ const depModule = await moduleGraph.ensureEntryFromUrl(uncleanUrl, ssr)
if (depModule.lastHMRTimestamp > 0) {
url = injectQuery(url, `t=${depModule.lastHMRTimestamp}`)
}
diff --git a/packages/vite/src/node/server/moduleGraph.ts b/packages/vite/src/node/server/moduleGraph.ts
index f09e741f..75d0bcf7 100644
--- a/packages/vite/src/node/server/moduleGraph.ts
+++ b/packages/vite/src/node/server/moduleGraph.ts
@@ -160,7 +160,10 @@ export class ModuleGraph {
let mod = this.urlToModuleMap.get(url)
if (!mod) {
mod = new ModuleNode(url)
- if (meta) mod.meta = meta
+ // A module with the same 'resolveId' might already exist under
+ // a different URL. Make sure we inherit its 'meta'.
+ const existing = this.idToModuleMap.get(resolvedId)
+ mod.meta = {...existing?.meta, ...meta}
this.urlToModuleMap.set(url, mod)
mod.id = resolvedId
this.idToModuleMap.set(resolvedId, mod) I'm not a fan of this fix, but it does fix it and hopefully illustrate the problem. It will fail if the |
The normalizeUrl helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix, it won't be registered correctly in the module graph. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour and fixes vitejs#6766 Fix: vitejs#6766 * packages/vite/src/node/importGlob.ts (ResolvedUrl): Import it. (transformImportGlob): Use it. * packages/vite/src/node/plugins/importAnalysis.ts (ResolvedUrl): Import it. (normalizeUrl): Use it. Always return meta. (transform): Ensure moduleGraph is correctly built.
The normalizeUrl helper calls user plugins's resolveId() twice. * Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. * Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix, it won't be registered correctly in the module graph. This change makes it so that the second resolution call is actually passed the query suffix. Then when updating the moduleGraph for the correct queryless URL, the meta reply obtained before is preserved. This makes Vite's dev server match Rollup's plugin-calling behaviour and fixes vitejs#6766 Fix: vitejs#6766
I tested it in a Github codespace. I believe this will fix your issue: diff --git a/plugin.js b/plugin.js
index 20ac4f7..c4f07c2 100644
--- a/plugin.js
+++ b/plugin.js
@@ -4,11 +4,14 @@ export default {
plugins: [
{
enforce: 'pre',
- async resolveId(id) {
+ async resolveId(id, importer) {
let [file, query] = id.split('?');
- const probe = query && query.match(/xoption=([^&]+)/)
- const x = probe && Number(probe[1])
- if (x) return {id: path.resolve(file), meta: {x}}
+ const probe = query && query.match(/xoption=([^&]+)/);
+ const x = probe && Number(probe[1]);
+ if (isNaN(x)) return;
+ const resolved = await this.resolve(file, importer, {skipSelf: true});
+ if (!resolved) return;
+ return {...resolved, meta: { ...resolved.meta, x }};
},
async transform(blob, id) {
const x = this.getModuleInfo(id)?.meta?.x
|
On Sun, Feb 6, 2022 at 6:47 PM Alec Larson ***@***.***> wrote:
Did you try the minimal reproducible repo I constructed and attached?
I did, and my suggestion fixed it
OK. There must be some misunderstanding. The sentence you wrote on
Sat, 5 Feb 2022 22:31:40 -0800 (PST) goes
> The id property you return from resolveId is not a real file
But that is just not true. When my resolveId returns {id}, it is indeed a
real file.
I've added an assertion to prove it.
This plugin works with "bare" non-Vite Rollup and also works with `vite
build`,
which is mostly bare Rollup.
When either of the two suggestion commits are applied to Vite, then this
plugin works all around.
|
@aleclarson the minimal reproduction recipe I attached is just a proof of the bug. Yes, know I can use But applying the The bug in Vite is fixed by either one of those two commits (the first one Thanks for your time and work. |
Just wanted to add that the solution that I recommend, I hope you can consider what is a very small fix to a blind spot |
Please open a PR and we can get Evan's feedback |
This commit improves the parity of behaviour between 'vite build' and 'vite dev' when Rollup plugins retuning non-null 'meta' properties from resolveId() hooks are used. If one takes the Rollup behaviour to be any kind of reference in these cases, this is fixing a small bug in Vite, which was in a very large part already fixed by PR vitejs#5465. Here's an explanation of the faulty behaviour: The normalizeUrl() helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix being passed in the imported URL, that meta reply won't be registered correctly in the module graph and is not retrievable via getModuleInfo() later on. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour and fixes vitejs#6766. Fix: vitejs#6766 * packages/vite/src/node/importGlob.ts (ResolvedUrl): Import it. (transformImportGlob): Use it. * packages/vite/src/node/plugins/importAnalysis.ts (ResolvedUrl): Import it. (normalizeUrl): Use it. Always return meta. (transform): Ensure moduleGraph is correctly built.
Done. See. #6811 Shouldn't this issue be reopened so that that that PR (or any other PR...) can subsequentely close it? |
@patak-dev Just noticed there's a "rollup plugin compat" label, maybe add it here? |
This commit improves the parity of behaviour between 'vite build' and 'vite dev' when Rollup plugins retuning non-null 'meta' properties from resolveId() hooks are used. If one takes the Rollup behaviour to be any kind of reference in these cases, this is fixing a small bug in Vite, which was in a very large part already fixed by PR vitejs#5465. Here's an explanation of the faulty behaviour: The normalizeUrl() helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix being passed in the imported URL, that meta reply won't be registered correctly in the module graph and is not retrievable via getModuleInfo() later on. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour and fixes vitejs#6766. Fix: vitejs#6766 * packages/vite/src/node/importGlob.ts (ResolvedUrl): Import it. (transformImportGlob): Use it. * packages/vite/src/node/plugins/importAnalysis.ts (ResolvedUrl): Import it. (normalizeUrl): Use it. Always return meta. (transform): Ensure moduleGraph is correctly built.
This commit improves the parity of behaviour between 'vite build' and 'vite dev' when Rollup plugins retuning non-null 'meta' properties from resolveId() hooks are used. If one takes the Rollup behaviour to be any kind of reference in these cases, this is fixing a small bug in Vite, which was in a very large part already fixed by PR vitejs#5465. Here's an explanation of the faulty behaviour: The normalizeUrl() helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix being passed in the imported URL, that meta reply won't be registered correctly in the module graph and is not retrievable via getModuleInfo() later on. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour and fixes vitejs#6766. Fix: vitejs#6766 * packages/vite/src/node/importGlob.ts (ResolvedUrl): Import it. (transformImportGlob): Use it. * packages/vite/src/node/plugins/importAnalysis.ts (ResolvedUrl): Import it. (normalizeUrl): Use it. Always return meta. (transform): Ensure moduleGraph is correctly built.
This commit improves the parity of behaviour between 'vite build' and 'vite dev' when Rollup plugins retuning non-null 'meta' properties from resolveId() hooks are used. If one takes the Rollup behaviour to be any kind of reference in these cases, this is fixing a small bug in Vite, which was in a very large part already fixed by PR vitejs#5465. Here's an explanation of the faulty behaviour: The normalizeUrl() helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix being passed in the imported URL, that meta reply won't be registered correctly in the module graph and is not retrievable via getModuleInfo() later on. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour. Fixes vitejs#6766
This commit improves the parity of behaviour between 'vite build' and 'vite dev' when Rollup plugins retuning non-null 'meta' properties from resolveId() hooks are used. If one takes the Rollup behaviour to be any kind of reference in these cases, this is fixing a small bug in Vite, which was in a very large part already fixed by PR vitejs#5465. Here's an explanation of the faulty behaviour: The normalizeUrl() helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix being passed in the imported URL, that meta reply won't be registered correctly in the module graph and is not retrievable via getModuleInfo() later on. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour. Fixes vitejs#6766
This commit improves the parity of behaviour between 'vite build' and 'vite dev' when Rollup plugins retuning non-null 'meta' properties from resolveId() hooks are used. If one takes the Rollup behaviour to be any kind of reference in these cases, this is fixing a small bug in Vite, which was in a very large part already fixed by PR vitejs#5465. Here's an explanation of the faulty behaviour: The normalizeUrl() helper calls user plugins's resolveId() twice. - Once with the URL string containing a query suffix. Here it _ignores_ the meta reply. - Again, with the URL no longer containing said suffix. Here it doesn't ignore the meta reply. It is stored in the moduleGraph node. As can be seen, if the user's plugin meta reply depends on the query suffix being passed in the imported URL, that meta reply won't be registered correctly in the module graph and is not retrievable via getModuleInfo() later on. This change makes it so that the first call doesn't ignore the meta reply. This makes Vite's dev server match Rollup's plugin-calling behaviour. Fixes vitejs#6766
Describe the bug
In #5465 support for
moduleInfo.meta
is added to the dev server. This is a very welcome change that I look forward to using. Unforunately, behavioral parity betweenvite build
andvite dev
is not quite there yet. In the attached reproduction recipe the former succeeds while the latter fails. By "failing" I mean thetransform
hook is never called and doesn't inject an important transformation intofoo.js
. Here are relevant parts of the files.To be clear, this particular solution "never" worked with Vite before. However, before #5465, a workaround/hack (not shown) could be devised, because
getModuleInfo
called in heresolveId
hook would return a persistent empty object that could be used to fill in the shortcomings that #5465 hopes to address. Ironically, that workaround is now not possible anymore.If this is accepted as a bug, I'd be happy to provide a PR to fix this.
Reproduction
https://github.com/joaotavora/bug-vite-return-meta-from-resolve-id
System Info
Used Package Manager
npm
Logs
No response
Validations
The text was updated successfully, but these errors were encountered: