diff --git a/packages/vite/src/node/plugins/assetImportMetaUrl.ts b/packages/vite/src/node/plugins/assetImportMetaUrl.ts index d16b1ad7540b64..8e04cbf0cb16e8 100644 --- a/packages/vite/src/node/plugins/assetImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/assetImportMetaUrl.ts @@ -28,6 +28,7 @@ import { preloadHelperId } from './importAnalysisBuild' export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { const normalizedPublicDir = normalizePath(config.publicDir) let assetResolver: ResolveFn + let aliaResolver: ResolveFn return { name: 'vite:asset-import-meta-url', @@ -64,6 +65,22 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { const ast = this.parse(pureUrl) const templateLiteral = (ast as any).body[0].expression if (templateLiteral.expressions.length) { + let newUrl: string | undefined + // rawUrl could include alias, try to resolve it + aliaResolver ??= config.createResolver() + const resolvedUrl = await aliaResolver( + rawUrl.slice(1), + undefined, + true, + ) + if (resolvedUrl) { + newUrl = normalizePath(path.relative(config.root, resolvedUrl)) + if (!newUrl.startsWith('.')) { + newUrl = `/${newUrl}` + } + newUrl = '`' + newUrl + } + const pattern = buildGlobPattern(templateLiteral) if (pattern.startsWith('**')) { // don't transform for patterns like this @@ -86,9 +103,9 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin { index + exp.length, `new URL((import.meta.glob(${JSON.stringify( pattern, - )}, ${JSON.stringify( - globOptions, - )}))[${pureUrl}], self.location)`, + )}, ${JSON.stringify(globOptions)}))[${ + newUrl ?? pureUrl + }], self.location)`, ) continue } diff --git a/playground/assets/__tests__/assets.spec.ts b/playground/assets/__tests__/assets.spec.ts index 29d56820c6c4bf..732a7b6c00fa58 100644 --- a/playground/assets/__tests__/assets.spec.ts +++ b/playground/assets/__tests__/assets.spec.ts @@ -335,6 +335,18 @@ test('new URL(`./${dynamic}?abc`, import.meta.url)', async () => { ) }) +test('new URL(`@/${dynamic}`, import.meta.url)', async () => { + expect(await page.textContent('.dynamic-import-meta-url-1-alias')).toMatch( + isBuild ? 'data:image/png;base64' : '/foo/nested/icon.png', + ) + expect(await page.textContent('.dynamic-import-meta-url-2-alias')).toMatch( + assetMatch, + ) + expect(await page.textContent('.dynamic-import-meta-url-js-alias')).toMatch( + isBuild ? 'data:application/javascript;base64' : '/foo/nested/test.js', + ) +}) + test('new URL(`non-existent`, import.meta.url)', async () => { expect(await page.textContent('.non-existent-import-meta-url')).toMatch( new URL('non-existent', page.url()).pathname, diff --git a/playground/assets/index.html b/playground/assets/index.html index b9e857398b6c35..85a99b419888a2 100644 --- a/playground/assets/index.html +++ b/playground/assets/index.html @@ -231,6 +231,19 @@

new URL(`./${dynamic}?abc`, import.meta.url)

+

new URL(`@/${dynamic}`, import.meta.url)

+

+ + +

+

+ + +

+

+ +

+

new URL(`non-existent`, import.meta.url)

@@ -453,10 +466,24 @@

assets in noscript

testDynamicImportMetaUrlWithQuery('icon', 1) testDynamicImportMetaUrlWithQuery('asset', 2) + function testDynamicImportMetaUrlWithAlias(name, i) { + const metaUrl = new URL(`@/${name}.png`, import.meta.url) + text(`.dynamic-import-meta-url-${i}-alias`, metaUrl) + document.querySelector(`.dynamic-import-meta-url-img-${i}-alias`).src = + metaUrl + } + + testDynamicImportMetaUrlWithAlias('icon', 1) + testDynamicImportMetaUrlWithAlias('asset', 2) + { const name = 'test' + const js = new URL(`./nested/${name}.js`, import.meta.url).href text('.dynamic-import-meta-url-js', js) + + const aliasedJs = new URL(`@/${name}.js`, import.meta.url).href + text('.dynamic-import-meta-url-js-alias', aliasedJs) } {