fix: data missing from moduleInfo.meta#7477
Conversation
| if (mod) { | ||
| mod.meta = { ...mod.meta, ...resolvedMeta } | ||
| } else { | ||
| moduleGraph.ensureEntryFromResolved([ |
There was a problem hiding this comment.
This isn't a viable solution, because we want to avoid adding a ModuleNode to the module graph until it's been successfully loaded.
This comment is evidence of that desire:
vite/packages/vite/src/node/server/transformRequest.ts
Lines 208 to 210 in 7f535ac
There was a problem hiding this comment.
Well, we could always delete the ModuleNode if it fails to load.. :)
6888373 to
4f2470b
Compare
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
4f2470b to
a75bf4e
Compare
9ac5e60 to
f63979b
Compare
aleclarson
left a comment
There was a problem hiding this comment.
I did some variable name improvements on the way. LMK what you think!
| ), | ||
| ssr | ||
| ssr, | ||
| false |
There was a problem hiding this comment.
refactor: The default value of isSelfAccepting is now undefined, so we need to pass an explicit false value wherever nothing was previously passed.
| const mod = moduleGraph.urlToModuleMap.get(path) | ||
| if (mod && mod.isSelfAccepting && mod.lastHMRTimestamp > 0) { | ||
| const file = getShortName(mod.file!, config.root) | ||
| const file = getShortName(mod.file, config.root) |
There was a problem hiding this comment.
refactor: Removing nullability of ModuleNode.file as discussed with @patak-dev
| const dep = | ||
| typeof imported === 'string' | ||
| ? await this.ensureEntryFromUrl(imported, ssr) | ||
| ? this.urlToModuleMap.get(imported)! |
There was a problem hiding this comment.
Anything in importedModules has a module node at this point, thanks to the importAnalysis plugin.
| ): Promise<ModuleNode> { | ||
| const [url, resolvedId, meta] = await this.resolveUrl(rawUrl, ssr) | ||
| let mod = this.idToModuleMap.get(resolvedId) | ||
| ensureEntryFromResolved( |
There was a problem hiding this comment.
A new method that allows adding a module node without calling resolveUrl again.
| const unhashedId = removeDepVersionQuery(resolvedId) | ||
| if (this.idToModuleMap.has(unhashedId)) { | ||
| resolvedId = unhashedId |
There was a problem hiding this comment.
We have to strip the version query here and see if a module node exists without, as we can't safely remove it from inside ensureEntryFromUrl.
|
|
||
| export function isExplicitImportRequired(url: string): boolean { | ||
| return !isJSRequest(cleanUrl(url)) && !isCSSRequest(url) | ||
| return !isJSRequest(url) && !isCSSRequest(url) |
There was a problem hiding this comment.
I'm not quite sure how safe it is to change this, but it didn't break any tests (in fact, it fixed a couple tests that were broken by this PR). For example, when a .html?vue file has &lang.js at the end, we don't want to inject ?import because that leads to duplicate entries in the module graph. Let me know if this is a problematic solution.
| const isPreBundled = resolvedId.startsWith( | ||
| getDepsCacheDirPrefix(config) | ||
| ) | ||
| const isFileInsideRoot = | ||
| !isPreBundled && resolvedId.startsWith(root + '/') | ||
| const isFileOutsideRoot = | ||
| !isPreBundled && | ||
| !isFileInsideRoot && | ||
| fs.existsSync(cleanUrl(resolvedId)) |
There was a problem hiding this comment.
style: I hoisted these conditions to improve readability.
| // e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'` | ||
| if (resolved.id.startsWith(root + '/')) { | ||
| let resolvedUrl: string | ||
| if (isPreBundled || isFileOutsideRoot) { |
There was a problem hiding this comment.
I swapped the conditions so that isPreBundled || isFileOutsideRoot is checked before isFileInsideRoot, since it was possible (even common!) for an optimized dependency file to exist within the project root.
| unwrapId(url), | ||
| ssr, | ||
| canSkipImportAnalysis(url) | ||
| const depModule = moduleGraph.ensureEntryFromResolved( |
There was a problem hiding this comment.
Replaced ensureEntryFromUrl call with ensureEntryFromResolved to avoid the extra resolveUrl call
| } | ||
| } | ||
|
|
||
| if (isExternalUrl(normalizedUrl) || isDataUrl(normalizedUrl)) { |
There was a problem hiding this comment.
Avoiding adding external URLs and data URLs to the module graph.
| } | ||
|
|
||
| // the module graph expects a url without timestamp query | ||
| let hmrUrl = removeTimestampQuery(stripBase(originalUrl, base)) |
There was a problem hiding this comment.
Have to remove ?t= to avoid duplicate module graph entry, but can't overwrite originalUrl since we need that to know if the URL was changed.
|
@aleclarson There's a lot of changes unrelated to the original fix which makes it hard to review. Are you able to rebase the changes and apply the fix for #6766 specifically? Or feel free to close this too and we can continue tracking progress in that issue. |
|
this should be fixed by the Environment API refactoring in Vite 6. If some of these issues persist, let's create smaller PRs to deal with them. |
|
This still seems to be an issue even with the Environment API: #19674 |
Follow-up to #6811
Fixes #6766