diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 0403009d4b69c4..13b2963e77e841 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -239,6 +239,13 @@ export function getAssetFilename( return assetHashToFilenameMap.get(config)?.get(hash) } +export function getPublicAssetFilename( + hash: string, + config: ResolvedConfig +): string | undefined { + return publicAssetUrlCache.get(config)?.get(hash) +} + export function resolveAssetFileNames( config: ResolvedConfig ): string | ((chunkInfo: PreRenderedAsset) => string) { diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 5287e6e5208ab5..d9e57e44086497 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -34,6 +34,8 @@ import { assetUrlRE, checkPublicFile, getAssetFilename, + getPublicAssetFilename, + publicAssetUrlRE, urlToBuiltUrl } from './asset' import { isCSSRequest } from './css' @@ -606,13 +608,16 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { for (const [id, html] of processedHtml) { const relativeUrlPath = path.posix.relative(config.root, id) const assetsBase = getBaseInHTML(relativeUrlPath, config) - const toOutputAssetFilePath = (filename: string) => { + const toOutputAssetFilePath = ( + filename: string, + type: 'asset' | 'public' = 'asset' + ) => { if (isExternalUrl(filename)) { return filename } else { return toOutputFilePathInHtml( filename, - 'asset', + type, relativeUrlPath, 'html', config, @@ -709,6 +714,15 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { ) }) + result = result.replace(publicAssetUrlRE, (_, fileHash) => { + return normalizePath( + toOutputAssetFilePath( + getPublicAssetFilename(fileHash, config)!, + 'public' + ) + ) + }) + if (chunk && canInlineEntry) { // all imports from entry have been inlined to html, prevent rollup from outputting it delete bundle[chunk.fileName] diff --git a/playground/assets/__tests__/assets.spec.ts b/playground/assets/__tests__/assets.spec.ts index c815714469b63b..898c355d18235a 100644 --- a/playground/assets/__tests__/assets.spec.ts +++ b/playground/assets/__tests__/assets.spec.ts @@ -364,3 +364,11 @@ test('relative path in html asset', async () => { expect(await page.textContent('.relative-js')).toMatch('hello') expect(await getColor('.relative-css')).toMatch('red') }) + +test('url to public folder', async () => { + expect(await getBg('.style-public-assets')).toContain(iconMatch) + // TODO: To investigate why `await getBg('.inline-style-public') === "url("http://localhost:5173/icon.png")"` + // It supposes to be `url("http://localhost:5173/static/icon.png")` + // (I built the playground to verify) + expect(await getBg('.inline-style-public')).toContain(iconMatch) +}) diff --git a/playground/assets/index.html b/playground/assets/index.html index f4eb70074f32c9..f0f5d9f0cd39c3 100644 --- a/playground/assets/index.html +++ b/playground/assets/index.html @@ -272,7 +272,9 @@

from public folder

background: url('/icon.png'); } -

inline style

+

+ inline style +

use style class

@import