Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(assets): allow new URL to resolve package assets #7837

Merged
merged 5 commits into from
Sep 23, 2022
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
2 changes: 0 additions & 2 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import {
getDepsCacheDir,
initDepsOptimizer
} from './optimizer'
import { assetImportMetaUrlPlugin } from './plugins/assetImportMetaUrl'
import { loadFallbackPlugin } from './plugins/loadFallback'
import type { PackageData } from './packages'
import { watchPackageDataPlugin } from './packages'
Expand Down Expand Up @@ -310,7 +309,6 @@ export function resolveBuildPlugins(config: ResolvedConfig): {
watchPackageDataPlugin(config),
...(usePluginCommonjs ? [commonjsPlugin(options.commonjsOptions)] : []),
dataURIPlugin(),
assetImportMetaUrlPlugin(config),
...(options.rollupOptions.plugins
? (options.rollupOptions.plugins.filter(Boolean) as Plugin[])
: [])
Expand Down
52 changes: 45 additions & 7 deletions packages/vite/src/node/plugins/assetImportMetaUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import MagicString from 'magic-string'
import { stripLiteral } from 'strip-literal'
import type { Plugin } from '../plugin'
import type { ResolvedConfig } from '../config'
import { transformStableResult } from '../utils'
import type { ResolveFn } from '../'
import {
isParentDirectory,
normalizePath,
slash,
transformStableResult
} from '../utils'
import { fileToUrl } from './asset'
import { preloadHelperId } from './importAnalysisBuild'

Expand All @@ -18,6 +24,9 @@ import { preloadHelperId } from './importAnalysisBuild'
* ```
*/
export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
const normalizedPublicDir = normalizePath(config.publicDir)
let assetResolver: ResolveFn

return {
name: 'vite:asset-import-meta-url',
async transform(code, id, options) {
bluwy marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -63,16 +72,45 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
}

const url = rawUrl.slice(1, -1)
const file = path.resolve(path.dirname(id), url)
// Get final asset URL. Catch error if the file does not exist,
// in which we can resort to the initial URL and let it resolve in runtime
const builtUrl = await fileToUrl(file, config, this).catch(() => {
let file: string | undefined
if (url.startsWith('.')) {
file = slash(path.resolve(path.dirname(id), url))
} else {
assetResolver ??= config.createResolver({
extensions: [],
mainFields: [],
tryIndex: false,
preferRelative: true
})
file = await assetResolver(url, id)
file ??= url.startsWith('/')
? slash(path.join(config.publicDir, url))
: slash(path.resolve(path.dirname(id), url))
}

// Get final asset URL. If the file does not exist,
// we fall back to the initial URL and let it resolve in runtime
let builtUrl: string | undefined
if (file) {
try {
if (isParentDirectory(normalizedPublicDir, file)) {
const publicPath =
'/' + path.posix.relative(normalizedPublicDir, file)
builtUrl = await fileToUrl(publicPath, config, this)
} else {
builtUrl = await fileToUrl(file, config, this)
}
} catch {
// do nothing, we'll log a warning after this
}
}
if (!builtUrl) {
const rawExp = code.slice(index, index + exp.length)
config.logger.warnOnce(
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime`
)
return url
})
builtUrl = url
}
s.overwrite(
index,
index + exp.length,
Expand Down
2 changes: 2 additions & 0 deletions packages/vite/src/node/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { preAliasPlugin } from './preAlias'
import { definePlugin } from './define'
import { ssrRequireHookPlugin } from './ssrRequireHook'
import { workerImportMetaUrlPlugin } from './workerImportMetaUrl'
import { assetImportMetaUrlPlugin } from './assetImportMetaUrl'
import { ensureWatchPlugin } from './ensureWatch'
import { metadataPlugin } from './metadata'
import { dynamicImportVarsPlugin } from './dynamicImportVars'
Expand Down Expand Up @@ -88,6 +89,7 @@ export async function resolvePlugins(
isBuild && config.build.ssr ? ssrRequireHookPlugin(config) : null,
isBuild && buildHtmlPlugin(config),
workerImportMetaUrlPlugin(config),
assetImportMetaUrlPlugin(config),
...buildPlugins.pre,
dynamicImportVarsPlugin(config),
importGlobPlugin(config),
Expand Down
41 changes: 29 additions & 12 deletions packages/vite/src/node/plugins/workerImportMetaUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import type { Plugin } from '../plugin'
import {
cleanUrl,
injectQuery,
normalizePath,
parseRequest,
slash,
transformStableResult
} from '../utils'
import { getDepsOptimizer } from '../optimizer'
import type { ResolveFn } from '..'
import type { WorkerType } from './worker'
import { WORKER_FILE_ID, workerFileToUrl } from './worker'
import { fileToUrl } from './asset'
Expand Down Expand Up @@ -71,6 +72,7 @@ function getWorkerType(raw: string, clean: string, i: number): WorkerType {

export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
const isBuild = config.command === 'build'
let workerResolver: ResolveFn

return {
name: 'vite:worker-import-meta-url',
Expand Down Expand Up @@ -112,22 +114,37 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
cleanString,
index + allExp.length
)
const file = normalizePath(
path.resolve(path.dirname(id), rawUrl.slice(1, -1))
)
const url = rawUrl.slice(1, -1)
let file: string | undefined
if (url.startsWith('.')) {
file = path.resolve(path.dirname(id), url)
} else {
workerResolver ??= config.createResolver({
extensions: [],
tryIndex: false,
preferRelative: true
})
file = await workerResolver(url, id)
file ??= url.startsWith('/')
? slash(path.join(config.publicDir, url))
: slash(path.resolve(path.dirname(id), url))
}

let url: string
let builtUrl: string
if (isBuild) {
getDepsOptimizer(config, ssr)?.registerWorkersSource(id)
url = await workerFileToUrl(config, file, query)
builtUrl = await workerFileToUrl(config, file, query)
} else {
url = await fileToUrl(cleanUrl(file), config, this)
url = injectQuery(url, WORKER_FILE_ID)
url = injectQuery(url, `type=${workerType}`)
builtUrl = await fileToUrl(cleanUrl(file), config, this)
builtUrl = injectQuery(builtUrl, WORKER_FILE_ID)
builtUrl = injectQuery(builtUrl, `type=${workerType}`)
}
s.overwrite(urlIndex, urlIndex + exp.length, JSON.stringify(url), {
contentOnly: true
})
s.overwrite(
urlIndex,
urlIndex + exp.length,
`new URL(${JSON.stringify(builtUrl)}, self.location)`,
poyoho marked this conversation as resolved.
Show resolved Hide resolved
{ contentOnly: true }
)
}

if (s) {
Expand Down
10 changes: 10 additions & 0 deletions playground/assets/__tests__/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,16 @@ test('new URL(..., import.meta.url)', async () => {
expect(await page.textContent('.import-meta-url')).toMatch(assetMatch)
})

test('new URL("@/...", import.meta.url)', async () => {
expect(await page.textContent('.import-meta-url-dep')).toMatch(assetMatch)
})

test('new URL("/...", import.meta.url)', async () => {
expect(await page.textContent('.import-meta-url-base-path')).toMatch(
iconMatch
)
})

test('new URL(`${dynamic}`, import.meta.url)', async () => {
expect(await page.textContent('.dynamic-import-meta-url-1')).toMatch(
isBuild ? 'data:image/png;base64' : '/foo/nested/icon.png'
Expand Down
18 changes: 18 additions & 0 deletions playground/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ <h2>new URL('...', import.meta.url)</h2>
<img class="import-meta-url-img" />
<code class="import-meta-url"></code>

<h2>new URL('@/...', import.meta.url)</h2>
<img class="import-meta-url-dep-img" />
<code class="import-meta-url-dep"></code>

<h2>new URL('/...', import.meta.url)</h2>
<img class="import-meta-url-base-path-img" />
<code class="import-meta-url-base-path"></code>

<h2>new URL('...', import.meta.url,) (with comma)</h2>
<img class="import-meta-url-img-comma" />
<code class="import-meta-url-comma"></code>
Expand Down Expand Up @@ -354,6 +362,16 @@ <h3>style in svg</h3>
text('.import-meta-url', metaUrl)
document.querySelector('.import-meta-url-img').src = metaUrl

const metaUrlDep = new URL('@/asset.png', import.meta.url)
text('.import-meta-url-dep', metaUrlDep)
document.querySelector('.import-meta-url-dep-img').src = metaUrlDep

// testing URLs for public assets served at the public base path
// equivalent to `new URL(`${import.meta.env.BASE_URL}/icon.png`, self.location)
const metaUrlBasePath = new URL('/icon.png', import.meta.url)
text('.import-meta-url-base-path', metaUrlBasePath)
document.querySelector('.import-meta-url-base-path-img').src = metaUrlBasePath

// prettier-ignore
const metaUrlWithComma = new URL('./nested/asset.png', import.meta.url,)
text('.import-meta-url-comma', metaUrlWithComma)
Expand Down
10 changes: 10 additions & 0 deletions playground/worker/__tests__/es/es-worker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ describe.runIf(isBuild)('build', () => {
})

test('module worker', async () => {
await untilUpdated(
() => page.textContent('.worker-import-meta-url'),
'A string',
true
)
await untilUpdated(
() => page.textContent('.worker-import-meta-url-resolve'),
'A string',
true
)
await untilUpdated(
() => page.textContent('.shared-worker-import-meta-url'),
'A string',
Expand Down
8 changes: 8 additions & 0 deletions playground/worker/__tests__/iife/iife-worker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ describe.runIf(isBuild)('build', () => {
})

test('module worker', async () => {
await untilUpdated(
() => page.textContent('.worker-import-meta-url'),
'A string'
)
await untilUpdated(
() => page.textContent('.worker-import-meta-url-resolve'),
'A string'
)
await untilUpdated(
() => page.textContent('.shared-worker-import-meta-url'),
'A string'
Expand Down
6 changes: 6 additions & 0 deletions playground/worker/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ <h2 class="format-iife">format iife:</h2>
</p>
<code class="worker-import-meta-url"></code>

<p>
new Worker(new URL('@/url-worker', import.meta.url), { type: 'module' })
<span class="classname">.worker-import-meta-url-resolve</span>
</p>
<code class="worker-import-meta-url-resolve"></code>

<p>
new SharedWorker(new URL('./url-shared-worker.js', import.meta.url), { type:
'module' })
Expand Down
5 changes: 5 additions & 0 deletions playground/worker/vite.config-es.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ const vite = require('vite')
module.exports = vite.defineConfig({
base: '/es/',
enforce: 'pre',
resolve: {
alias: {
'@': __dirname
}
},
worker: {
format: 'es',
plugins: [vueJsx()],
Expand Down
5 changes: 5 additions & 0 deletions playground/worker/vite.config-iife.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ const vite = require('vite')

module.exports = vite.defineConfig({
base: '/iife/',
resolve: {
alias: {
'@': __dirname
}
},
worker: {
format: 'iife',
plugins: [
Expand Down
5 changes: 5 additions & 0 deletions playground/worker/vite.config-relative-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ const vite = require('vite')

module.exports = vite.defineConfig({
base: './',
resolve: {
alias: {
'@': __dirname
}
},
worker: {
format: 'es',
plugins: [vueJsx()],
Expand Down
5 changes: 5 additions & 0 deletions playground/worker/vite.config-sourcemap.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ module.exports = vite.defineConfig((sourcemap) => {
base: `/iife-${
typeof sourcemap === 'boolean' ? 'sourcemap' : 'sourcemap-' + sourcemap
}/`,
resolve: {
alias: {
'@': __dirname
}
},
worker: {
format: 'iife',
plugins: [vueJsx()],
Expand Down
9 changes: 9 additions & 0 deletions playground/worker/worker/main-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ w.addEventListener('message', (ev) =>
text('.worker-import-meta-url', JSON.stringify(ev.data))
)

// url import worker with alias path
const wResolve = new Worker(
new URL('@/url-worker.js', import.meta.url),
/* @vite-ignore */ workerOptions
)
wResolve.addEventListener('message', (ev) =>
text('.worker-import-meta-url-resolve', JSON.stringify(ev.data))
)

const genWorkerName = () => 'module'
const w2 = new SharedWorker(
new URL('../url-shared-worker.js', import.meta.url),
Expand Down