Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/vite/src/node/plugins/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ import { getImportMapFilename } from './html'
// referenceId is base64url but replaces - with $
export const assetUrlRE: RegExp = /__VITE_ASSET__([\w$]+)__/g

const encodedHashPlaceholderRE = /!~%7B([\w$]{1,17})%7D~/g
function unescapeHashPlaceholders(uri: string): string {
return uri.replace(encodedHashPlaceholderRE, '!~{$1}~')
}

interface FileUrlMetadata {
asFileUrl: boolean
}
Expand Down Expand Up @@ -329,7 +334,9 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
toRelativeRuntime,
)
return typeof replacement === 'string'
? JSON.stringify(encodeURIPath(replacement))
? JSON.stringify(
unescapeHashPlaceholders(encodeURIPath(replacement)),
)
: replacement.runtime
},

Expand Down
14 changes: 14 additions & 0 deletions playground/assets/__tests__/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,20 @@ describe('asset imports from js', () => {
})
})

describe.runIf(isBuild)('file URL emitted by an external plugin', () => {
test('replaces the preliminary hash', async () => {
expect(await page.textContent('.emitted-worker-url')).toMatch(
/^\/foo\/bar\/assets\/emitted-worker-[-\w]{8}\.js$/,
)
})

test('loads the emitted chunk', async () => {
await expect
.poll(() => page.textContent('.emitted-worker-result'))
.toBe('worker loaded')
})
})

describe('css url() references', () => {
test('fonts', async () => {
expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ describe('asset imports from js', () => {
})
})

test.runIf(isBuild)('loads the emitted worker', async () => {
await expect
.poll(() => page.textContent('.emitted-worker-result'))
.toBe('worker loaded')
})

describe('css url() references', () => {
test('fonts', async () => {
expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ describe('asset imports from js', () => {
})
})

test.runIf(isBuild)('loads the emitted worker', async () => {
await expect
.poll(() => page.textContent('.emitted-worker-result'))
.toBe('worker loaded')
})

describe('css url() references', () => {
test('fonts', async () => {
expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ describe('asset imports from js', () => {
})
})

test.runIf(isBuild)('loads the emitted worker', async () => {
await expect
.poll(() => page.textContent('.emitted-worker-result'))
.toBe('worker loaded')
})

describe('css url() references', () => {
test('fonts', async () => {
expect(
Expand Down
6 changes: 6 additions & 0 deletions playground/assets/__tests__/url-base/assets-url-base.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ describe('asset imports from js', () => {
})
})

test.runIf(isBuild)('loads the emitted worker', async () => {
await expect
.poll(() => page.textContent('.emitted-worker-result'))
.toBe('worker loaded')
})

describe('css url() references', () => {
test('fonts', async () => {
expect(
Expand Down
1 change: 1 addition & 0 deletions playground/assets/asset/emitted-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
self.postMessage('worker loaded')
10 changes: 10 additions & 0 deletions playground/assets/asset/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import emittedWorkerUrl from 'virtual:emitted-worker-url'

function text(el, text) {
document.querySelector(el).textContent = text
}
text('.relative-js', 'hello')

if (emittedWorkerUrl) {
text('.emitted-worker-url', emittedWorkerUrl)
const worker = new Worker(emittedWorkerUrl, { type: 'module' })
worker.addEventListener('message', ({ data }) => {
text('.emitted-worker-result', data)
})
}
4 changes: 4 additions & 0 deletions playground/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ <h2>Asset Imports from JS</h2>
</li>
</ul>

<h2>File URL emitted by an external plugin</h2>
<code class="emitted-worker-url">pending</code>
<code class="emitted-worker-result">pending</code>

<h2>CSS url references</h2>
<div>Font should be loaded (all text should be italic)</div>
<div class="css-url-absolute">
Expand Down
1 change: 1 addition & 0 deletions playground/assets/vite.config-runtime-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default defineConfig({
},
},
plugins: [
...baseConfig.plugins,
{
name: 'dynamic-base-assets-globals',
transformIndexHtml(_, ctx) {
Expand Down
20 changes: 20 additions & 0 deletions playground/assets/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ export default defineConfig({
},
},
assetsInclude: ['**/*.unknown', './nested/*.custom'],
plugins: [
{
name: 'emitted-worker-url',
resolveId(id) {
if (id === 'virtual:emitted-worker-url') {
return '\0virtual:emitted-worker-url'
}
},
load(id) {
if (id !== '\0virtual:emitted-worker-url') return
if (this.environment.mode !== 'build') return 'export default undefined'

const referenceId = this.emitFile({
type: 'chunk',
id: path.resolve(import.meta.dirname, 'asset/emitted-worker.js'),
})
return `export default import.meta.ROLLUP_FILE_URL_${referenceId}`
},
},
],
build: {
outDir: 'dist/foo',
assetsInlineLimit: 8000, // 8 kB
Expand Down
Loading