diff --git a/packages/vite/src/node/plugins/importMetaGlob.ts b/packages/vite/src/node/plugins/importMetaGlob.ts index 10fe5f9120bbd5..7ff08e544a78c6 100644 --- a/packages/vite/src/node/plugins/importMetaGlob.ts +++ b/packages/vite/src/node/plugins/importMetaGlob.ts @@ -13,7 +13,7 @@ import type { TemplateLiteral, } from 'estree' import { parseExpressionAt } from 'acorn' -import type { RollupError } from 'rollup' +import type { CustomPluginOptions, RollupError } from 'rollup' import { findNodeAt } from 'acorn-walk' import MagicString from 'magic-string' import fg from 'fast-glob' @@ -75,7 +75,8 @@ export function importGlobPlugin(config: ResolvedConfig): Plugin { code, id, config.root, - (im) => this.resolve(im, id).then((i) => i?.id || im), + (im, _, options) => + this.resolve(im, id, options).then((i) => i?.id || im), config.isProduction, config.experimental.importGlobRestoreExtension, ) @@ -546,6 +547,12 @@ export async function transformGlobImport( type IdResolver = ( id: string, importer?: string, + options?: { + assertions?: Record + custom?: CustomPluginOptions + isEntry?: boolean + skipSelf?: boolean + }, ) => Promise | string | undefined function globSafePath(path: string) { @@ -594,7 +601,16 @@ export async function toAbsoluteGlob( if (glob.startsWith('../')) return pre + posix.join(dir, glob) if (glob.startsWith('**')) return pre + glob - const resolved = normalizePath((await resolveId(glob, importer)) || glob) + const isSubImportsPattern = glob.startsWith('#') && glob.includes('*') + + const resolved = normalizePath( + (await resolveId(glob, importer, { + custom: { 'vite:import-glob': { isSubImportsPattern } }, + })) || glob, + ) + if (isSubImportsPattern) { + return join(root, resolved) + } if (isAbsolute(resolved)) { return pre + globSafeResolvedPath(resolved, glob) } diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 4b28e810ab2c6e..a7d898efa5a566 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -185,6 +185,10 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin { ) if (resolvedImports) { id = resolvedImports + + if (resolveOpts.custom?.['vite:import-glob']?.isSubImportsPattern) { + return id + } } if (importer) { diff --git a/playground/glob-import/__tests__/glob-import.spec.ts b/playground/glob-import/__tests__/glob-import.spec.ts index 34b77127cdb1e0..cf1b6c199e73aa 100644 --- a/playground/glob-import/__tests__/glob-import.spec.ts +++ b/playground/glob-import/__tests__/glob-import.spec.ts @@ -240,3 +240,7 @@ test('escapes special chars in globs without mangling user supplied glob suffix' .sort() expect(expectedNames).toEqual(foundAliasNames) }) + +test('sub imports', async () => { + expect(await page.textContent('.sub-imports')).toMatch('bar foo') +}) diff --git a/playground/glob-import/imports-path/bar.js b/playground/glob-import/imports-path/bar.js new file mode 100644 index 00000000000000..4548a26ba14dc8 --- /dev/null +++ b/playground/glob-import/imports-path/bar.js @@ -0,0 +1 @@ +export default 'bar' diff --git a/playground/glob-import/imports-path/foo.js b/playground/glob-import/imports-path/foo.js new file mode 100644 index 00000000000000..7e942cf45c8a37 --- /dev/null +++ b/playground/glob-import/imports-path/foo.js @@ -0,0 +1 @@ +export default 'foo' diff --git a/playground/glob-import/index.html b/playground/glob-import/index.html index a899d244326f68..b726965ff62067 100644 --- a/playground/glob-import/index.html +++ b/playground/glob-import/index.html @@ -21,6 +21,8 @@

Escape relative glob


 

Escape alias glob


+

Sub imports

+

 
 
 
 
+
+
 
diff --git a/playground/glob-import/package.json b/playground/glob-import/package.json
index 66d4667336a1a5..7d9104ab431c28 100644
--- a/playground/glob-import/package.json
+++ b/playground/glob-import/package.json
@@ -3,6 +3,9 @@
   "private": true,
   "version": "0.0.0",
   "type": "module",
+  "imports": {
+    "#imports/*": "./imports-path/*"
+  },
   "scripts": {
     "dev": "vite",
     "build": "vite build",