From 4c75492cca5e2eef379b4aa730724e36d9963c6c Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 29 Nov 2025 01:00:09 +0900 Subject: [PATCH] fix: fix external behavior with `deps.optimizer` (#9125) --- packages/vitest/src/node/resolver.ts | 5 ++++ pnpm-lock.yaml | 16 ++++++++++++ test/config/deps/optimizer/external/index.js | 1 + .../deps/optimizer/external/package.json | 6 +++++ test/config/deps/optimizer/optimized/index.js | 1 + .../deps/optimizer/optimized/package.json | 6 +++++ .../fixtures/optimizer/external/basic.test.ts | 7 ++++++ .../optimizer/external/vitest.config.ts | 25 +++++++++++++++++++ test/config/package.json | 2 ++ test/config/test/optimizer.test.ts | 15 +++++++++++ 10 files changed, 84 insertions(+) create mode 100644 test/config/deps/optimizer/external/index.js create mode 100644 test/config/deps/optimizer/external/package.json create mode 100644 test/config/deps/optimizer/optimized/index.js create mode 100644 test/config/deps/optimizer/optimized/package.json create mode 100644 test/config/fixtures/optimizer/external/basic.test.ts create mode 100644 test/config/fixtures/optimizer/external/vitest.config.ts create mode 100644 test/config/test/optimizer.test.ts diff --git a/packages/vitest/src/node/resolver.ts b/packages/vitest/src/node/resolver.ts index 991c0ac1a..a2c2bcb86 100644 --- a/packages/vitest/src/node/resolver.ts +++ b/packages/vitest/src/node/resolver.ts @@ -3,6 +3,7 @@ import { existsSync, promises as fsp } from 'node:fs' import { isBuiltin } from 'node:module' import { pathToFileURL } from 'node:url' import { KNOWN_ASSET_RE } from '@vitest/utils/constants' +import { cleanUrl } from '@vitest/utils/helpers' import { findNearestPackageData } from '@vitest/utils/resolver' import * as esModuleLexer from 'es-module-lexer' import { dirname, extname, join, resolve } from 'pathe' @@ -109,6 +110,10 @@ export function guessCJSversion(id: string): string | undefined { // The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98 async function isValidNodeImport(id: string) { + // clean url to strip off `?v=...` query etc. + // node can natively import files with query params, so externalizing them is safe. + id = cleanUrl(id) + const extension = extname(id) if (BUILTIN_EXTENSIONS.has(extension)) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bf28cf79..996c999e3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1226,6 +1226,12 @@ importers: '@vitest/test-dep-conditions': specifier: file:./deps/test-dep-conditions version: file:test/config/deps/test-dep-conditions + '@vitest/test-dep-optimizer-external': + specifier: file:./deps/optimizer/external + version: file:test/config/deps/optimizer/external + '@vitest/test-dep-optimizer-optimized': + specifier: file:./deps/optimizer/optimized + version: file:test/config/deps/optimizer/optimized inline-dep: specifier: file:./deps/vite-ssr-resolve/inline-dep version: file:test/config/deps/vite-ssr-resolve/inline-dep @@ -4701,6 +4707,12 @@ packages: '@vitest/test-dep-nested-cjs@file:test/core/deps/dep-nested-cjs': resolution: {directory: test/core/deps/dep-nested-cjs, type: directory} + '@vitest/test-dep-optimizer-external@file:test/config/deps/optimizer/external': + resolution: {directory: test/config/deps/optimizer/external, type: directory} + + '@vitest/test-dep-optimizer-optimized@file:test/config/deps/optimizer/optimized': + resolution: {directory: test/config/deps/optimizer/optimized, type: directory} + '@vitest/test-dep1@file:test/core/deps/dep1': resolution: {directory: test/core/deps/dep1, type: directory} @@ -12848,6 +12860,10 @@ snapshots: '@vitest/test-dep-nested-cjs@file:test/core/deps/dep-nested-cjs': {} + '@vitest/test-dep-optimizer-external@file:test/config/deps/optimizer/external': {} + + '@vitest/test-dep-optimizer-optimized@file:test/config/deps/optimizer/optimized': {} + '@vitest/test-dep1@file:test/core/deps/dep1': {} '@vitest/test-dep2@file:test/core/deps/dep2': diff --git a/test/config/deps/optimizer/external/index.js b/test/config/deps/optimizer/external/index.js new file mode 100644 index 000000000..b1c6ea436 --- /dev/null +++ b/test/config/deps/optimizer/external/index.js @@ -0,0 +1 @@ +export default {} diff --git a/test/config/deps/optimizer/external/package.json b/test/config/deps/optimizer/external/package.json new file mode 100644 index 000000000..f81140f15 --- /dev/null +++ b/test/config/deps/optimizer/external/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitest/test-dep-optimizer-external", + "type": "module", + "private": true, + "main": "./index.js" +} diff --git a/test/config/deps/optimizer/optimized/index.js b/test/config/deps/optimizer/optimized/index.js new file mode 100644 index 000000000..b1c6ea436 --- /dev/null +++ b/test/config/deps/optimizer/optimized/index.js @@ -0,0 +1 @@ +export default {} diff --git a/test/config/deps/optimizer/optimized/package.json b/test/config/deps/optimizer/optimized/package.json new file mode 100644 index 000000000..ce84ba1b6 --- /dev/null +++ b/test/config/deps/optimizer/optimized/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitest/test-dep-optimizer-optimized", + "type": "module", + "private": true, + "main": "./index.js" +} diff --git a/test/config/fixtures/optimizer/external/basic.test.ts b/test/config/fixtures/optimizer/external/basic.test.ts new file mode 100644 index 000000000..0603f3398 --- /dev/null +++ b/test/config/fixtures/optimizer/external/basic.test.ts @@ -0,0 +1,7 @@ +import { it, expect } from "vitest"; +// @ts-ignore +import * as testDep from "@vitest/test-dep-optimizer-external" + +it("passes", () => { + expect(testDep.default).toBeDefined(); +}); diff --git a/test/config/fixtures/optimizer/external/vitest.config.ts b/test/config/fixtures/optimizer/external/vitest.config.ts new file mode 100644 index 000000000..783c5f8b8 --- /dev/null +++ b/test/config/fixtures/optimizer/external/vitest.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + deps: { + optimizer: { + ssr: { + enabled: true, + // need at least one to trigger dep optimization + include: ["@vitest/test-dep-optimizer-optimized"], + }, + }, + }, + }, + plugins: [ + { + name: 'test-external', + transform(_code, id, _options) { + if (id.includes('test-dep-optimizer-external')) { + this.error('"@vitest/test-dep-optimizer-external" is expected to be externalized'); + } + }, + } + ] +}); diff --git a/test/config/package.json b/test/config/package.json index 77bab32ab..984aed97c 100644 --- a/test/config/package.json +++ b/test/config/package.json @@ -11,6 +11,8 @@ "@vitest/browser-preview": "workspace:*", "@vitest/browser-webdriverio": "workspace:*", "@vitest/test-dep-conditions": "file:./deps/test-dep-conditions", + "@vitest/test-dep-optimizer-external": "file:./deps/optimizer/external", + "@vitest/test-dep-optimizer-optimized": "file:./deps/optimizer/optimized", "inline-dep": "file:./deps/vite-ssr-resolve/inline-dep", "other-dep": "file:./deps/vite-ssr-resolve/other-dep", "ssr-no-external-dep": "file:./deps/vite-ssr-resolve/ssr-no-external-dep", diff --git a/test/config/test/optimizer.test.ts b/test/config/test/optimizer.test.ts new file mode 100644 index 000000000..12fb2b1c8 --- /dev/null +++ b/test/config/test/optimizer.test.ts @@ -0,0 +1,15 @@ +import { expect, it } from 'vitest' +import { runVitest } from '../../test-utils' + +it('external works with optimizer', async () => { + const { errorTree } = await runVitest({ + root: 'fixtures/optimizer/external', + }) + expect(errorTree()).toMatchInlineSnapshot(` + { + "basic.test.ts": { + "passes": "passed", + }, + } + `) +}) -- 2.51.2