Repository: vitejs/vite
File: packages/vite/src/node/plugins/importAnalysis.ts (TypeScript)

Code before:
        if (isExternalUrl(resolved.id)) {
          return [resolved.id, resolved.id]
        }

        const isRelative = url[0] === '.'
        const isSelfImport = !isRelative && cleanUrl(url) === cleanUrl(importer)

        url = normalizeResolvedIdToUrl(environment, url, resolved)

        // make the URL browser-valid
        if (environment.config.consumer === 'client') {
          // mark non-js/css imports with `?import`
          if (isExplicitImportRequired(url)) {
            url = injectQuery(url, 'import')
          } else if (
            (isRelative || isSelfImport) &&
            !DEP_VERSION_RE.test(url)
          ) {
            // If the url isn't a request for a pre-bundled common chunk,
            // for relative js/css imports, or self-module virtual imports
            // (e.g. vue blocks), inherit importer's version query
            // do not do this for unknown type imports, otherwise the appended
            // query can break 3rd party plugin's extension checks.
            const versionMatch = DEP_VERSION_RE.exec(importer)
            if (versionMatch) {
              url = injectQuery(url, versionMatch[1])
            }
          }
        }

        try {
          // delay setting `isSelfAccepting` until the file is actually used (#7870)
          // We use an internal function to avoid resolving the url again
          const depModule = await moduleGraph._ensureEntryFromUrl(
            unwrapId(url),
            canSkipImportAnalysis(url) || forceSkipImportAnalysis,
            resolved,
          )
          // check if the dep has been hmr updated. If yes, we need to attach
          // its last updated timestamp to force the browser to fetch the most
          // up-to-date version of this module.
          if (
            environment.config.consumer === 'client' &&
            depModule.lastHMRTimestamp > 0
          ) {
            url = injectQuery(url, `t=${depModule.lastHMRTimestamp}`)
          }
        } catch (e: any) {
          // it's possible that the dep fails to resolve (non-existent import)
          // attach location to the missing import
          e.pos = pos

Review comment (bug):
This was causing `moduleGraph._ensureEntryFromUrl` below to be called with
```js
await moduleGraph._ensureEntryFromUrl(
    unwrapId(url), // url with `?v=` query
    canSkipImportAnalysis(url) || forceSkipImportAnalysis,
    resolved, // resolved result without `?v=` query
  )
```
and caused the `moduleGraph.urlToModuleMap` to have a mapping from "url with v query" to "id without v query".
This lead `id` in `doTransform` to resolve "url with v query" to "id without v query", and made the new condition in `vite:optimized-deps` plugin to fail.
https://github.com/vitejs/vite/blob/c4d5940e1519a2d9d68505a911123398a136e60b/packages/vite/src/node/server/transformRequest.ts#L166-L171
https://github.com/vitejs/vite/pull/20439/files#diff-0648e3b1da8ac697354cfca37ada638d3a353be4b3312211c6b131597f6ca101R80

To fix that, I moved this if block after the `moduleGraph._ensureEntryFromUrl` call.
Given that `_ensureEntryFromUrl` removes some query internally,
https://github.com/vitejs/vite/blob/c4d5940e1519a2d9d68505a911123398a136e60b/packages/vite/src/node/server/moduleGraph.ts#L350
I think not adding `?v=` for the URL passed to `_ensureEntryFromUrl` should be fine.

Code after:
        if (isExternalUrl(resolved.id)) {
          return [resolved.id, resolved.id]
        }

        url = normalizeResolvedIdToUrl(environment, url, resolved)

        try {
          // delay setting `isSelfAccepting` until the file is actually used (#7870)
          // We use an internal function to avoid resolving the url again
          const depModule = await moduleGraph._ensureEntryFromUrl(
            unwrapId(url),
            canSkipImportAnalysis(url) || forceSkipImportAnalysis,
            resolved,
          )
          // check if the dep has been hmr updated. If yes, we need to attach
          // its last updated timestamp to force the browser to fetch the most
          // up-to-date version of this module.
          if (
            environment.config.consumer === 'client' &&
            depModule.lastHMRTimestamp > 0
          ) {
            url = injectQuery(url, `t=${depModule.lastHMRTimestamp}`)
          }
        } catch (e: any) {
          // it's possible that the dep fails to resolve (non-existent import)
          // attach location to the missing import
          e.pos = pos
          throw e
        }

        // make the URL browser-valid
        if (environment.config.consumer === 'client') {
          const isRelative = url[0] === '.'
          const isSelfImport =
            !isRelative && cleanUrl(url) === cleanUrl(importer)

          // mark non-js/css imports with `?import`
          if (isExplicitImportRequired(url)) {
            url = injectQuery(url, 'import')
          } else if (
            (isRelative || isSelfImport) &&
            !DEP_VERSION_RE.test(url)
          ) {
            // If the url isn't a request for a pre-bundled common chunk,
            // for relative js/css imports, or self-module virtual imports
            // (e.g. vue blocks), inherit importer's version query
            // do not do this for unknown type imports, otherwise the appended
            // query can break 3rd party plugin's extension checks.
            const versionMatch = DEP_VERSION_RE.exec(importer)
            if (versionMatch) {
              url = injectQuery(url, versionMatch[1])