Skip to content

Commit

Permalink
feat(indexHtml): support transform assets url to safe path (fix vitej…
Browse files Browse the repository at this point in the history
  • Loading branch information
sun0day committed Mar 10, 2023
1 parent dd7a2f1 commit b7d0ec4
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 9 deletions.
19 changes: 13 additions & 6 deletions packages/vite/src/node/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,31 @@ export function nodeIsElement(
return node.nodeName[0] !== '#'
}

function traverseNodes(
async function traverseNodes(
node: DefaultTreeAdapterMap['node'],
visitor: (node: DefaultTreeAdapterMap['node']) => void,
visitor: (node: DefaultTreeAdapterMap['node']) => void | Promise<void>,
) {
visitor(node)
const visitorPromise = visitor(node)

if (visitorPromise) {
await visitorPromise
}

if (
nodeIsElement(node) ||
node.nodeName === '#document' ||
node.nodeName === '#document-fragment'
) {
node.childNodes.forEach((childNode) => traverseNodes(childNode, visitor))
for (const childNode of node.childNodes) {
await traverseNodes(childNode, visitor)
}
}
}

export async function traverseHtml(
html: string,
filePath: string,
visitor: (node: DefaultTreeAdapterMap['node']) => void,
visitor: (node: DefaultTreeAdapterMap['node']) => void | Promise<void>,
): Promise<void> {
// lazy load compiler
const { parse } = await import('parse5')
Expand All @@ -176,7 +183,7 @@ export async function traverseHtml(
handleParseError(e, html, filePath)
},
})
traverseNodes(ast, visitor)
await traverseNodes(ast, visitor)
}

export function getScriptInfo(node: DefaultTreeAdapterMap['element']): {
Expand Down
8 changes: 6 additions & 2 deletions packages/vite/src/node/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,11 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin {
// /foo -> /fs-root/foo
if (asSrc && id.startsWith('/')) {
const fsPath = path.resolve(root, id.slice(1))
if ((res = tryFsResolve(fsPath, options))) {
const modulePath = path.resolve(root, `node_modules${id}`)
if (
(res =
tryFsResolve(fsPath, options) || tryFsResolve(modulePath, options))
) {
isDebug && debug(`[url] ${colors.cyan(id)} -> ${colors.dim(res)}`)
return ensureVersionQuery(res)
}
Expand Down Expand Up @@ -587,7 +591,7 @@ function tryResolveFile(
// path points to a node package
const pkg = loadPackageData(pkgPath, options.preserveSymlinks)
const resolved = resolvePackageEntry(file, pkg, targetWeb, options)
return resolved
return resolved + postfix
} catch (e) {
if (e.code !== 'ENOENT') {
throw e
Expand Down
2 changes: 2 additions & 0 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ export async function createServer(
const container = await createPluginContainer(config, moduleGraph, watcher)
const closeHttpServer = createServerCloseFn(httpServer)

moduleGraph.ensureEntryFromUrl(path.resolve(config.root, '_vite_entry_.js'))

let exitProcess: () => void

const server: ViteDevServer = {
Expand Down
40 changes: 39 additions & 1 deletion packages/vite/src/node/server/middlewares/indexHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
ensureWatchedFile,
fsPathFromId,
injectQuery,
isExternalUrl,
joinUrlSegments,
normalizePath,
processSrcSetSync,
Expand Down Expand Up @@ -122,6 +123,37 @@ const processNodeUrl = (
overwriteAttrValue(s, sourceCodeLocation, processedUrl)
}
}

const resolveAssetUrl = async (server: ViteDevServer, rawUrl: string) => {
if (isExternalUrl(rawUrl)) {
return rawUrl
}

const getUrlFromCode = (code: string) => code.match(/["'](.+)["']/)![1]

const transform = (url: string) =>
server.pluginContainer
.transform(
`import "${url}"`,
path.resolve(server.config.root, '_vite_entry_.js'),
)
.catch((_) => null)

rawUrl = rawUrl.replace(/^\//, '')

// fs-root/rawUrl | fs-root/node_modules/rawUrl
const source = (await transform(`./${rawUrl}`)) || (await transform(rawUrl))

if (!source) {
return source
}

return getUrlFromCode(source.code).replace(
new RegExp(`^${server.config.base}/`),
'/',
)
}

const devHtmlHook: IndexHtmlTransformHook = async (
html,
{ path: htmlPath, filename, server, originalUrl },
Expand Down Expand Up @@ -195,7 +227,7 @@ const devHtmlHook: IndexHtmlTransformHook = async (
)
}

await traverseHtml(html, filename, (node) => {
await traverseHtml(html, filename, async (node) => {
if (!nodeIsElement(node)) {
return
}
Expand Down Expand Up @@ -234,6 +266,12 @@ const devHtmlHook: IndexHtmlTransformHook = async (
for (const p of node.attrs) {
const attrKey = getAttrKey(p)
if (p.value && assetAttrs.includes(attrKey)) {
const url = await resolveAssetUrl(server!, p.value)

if (url) {
p.value = url
}

processNodeUrl(
p,
node.sourceCodeLocation!.attrs![attrKey],
Expand Down

0 comments on commit b7d0ec4

Please sign in to comment.