Skip to content

Commit

Permalink
fix(html): import expression in classic script for dev (#14595)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored Oct 12, 2023
1 parent a4a17b8 commit ea47b8f
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 41 deletions.
42 changes: 26 additions & 16 deletions packages/vite/src/node/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,22 +432,9 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
} else if (node.childNodes.length) {
const scriptNode =
node.childNodes.pop() as DefaultTreeAdapterMap['textNode']
const cleanCode = stripLiteral(scriptNode.value)

let match: RegExpExecArray | null
inlineImportRE.lastIndex = 0
while ((match = inlineImportRE.exec(cleanCode))) {
const { 1: url, index } = match
const startUrl = cleanCode.indexOf(url, index)
const start = startUrl + 1
const end = start + url.length - 2
const startOffset = scriptNode.sourceCodeLocation!.startOffset
scriptUrls.push({
start: start + startOffset,
end: end + startOffset,
url: scriptNode.value.slice(start, end),
})
}
scriptUrls.push(
...extractImportExpressionFromClassicScript(scriptNode),
)
}
}

Expand Down Expand Up @@ -889,6 +876,29 @@ export function findNeedTransformStyleAttribute(
return { attr, location }
}

export function extractImportExpressionFromClassicScript(
scriptTextNode: DefaultTreeAdapterMap['textNode'],
): ScriptAssetsUrl[] {
const startOffset = scriptTextNode.sourceCodeLocation!.startOffset
const cleanCode = stripLiteral(scriptTextNode.value)

const scriptUrls: ScriptAssetsUrl[] = []
let match: RegExpExecArray | null
inlineImportRE.lastIndex = 0
while ((match = inlineImportRE.exec(cleanCode))) {
const { 1: url, index } = match
const startUrl = cleanCode.indexOf(url, index)
const start = startUrl + 1
const end = start + url.length - 2
scriptUrls.push({
start: start + startOffset,
end: end + startOffset,
url: scriptTextNode.value.slice(start, end),
})
}
return scriptUrls
}

export interface HtmlTagDescriptor {
tag: string
attrs?: Record<string, string | boolean | undefined>
Expand Down
67 changes: 47 additions & 20 deletions packages/vite/src/node/server/middlewares/indexHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
addToHTMLProxyCache,
applyHtmlTransforms,
assetAttrsConfig,
extractImportExpressionFromClassicScript,
findNeedTransformStyleAttribute,
getAttrKey,
getScriptInfo,
Expand Down Expand Up @@ -103,17 +104,16 @@ function shouldPreTransform(url: string, config: ResolvedConfig) {

const startsWithWordCharRE = /^\w/

const isSrcSet = (attr: Token.Attribute) =>
attr.name === 'srcset' && attr.prefix === undefined
const processNodeUrl = (
attr: Token.Attribute,
sourceCodeLocation: Token.Location,
s: MagicString,
url: string,
useSrcSetReplacer: boolean,
config: ResolvedConfig,
htmlPath: string,
originalUrl?: string,
server?: ViteDevServer,
) => {
let url = attr.value || ''

): string | undefined => {
if (server?.moduleGraph) {
const mod = server.moduleGraph.urlToModuleMap.get(url)
if (mod && mod.lastHMRTimestamp > 0) {
Expand All @@ -124,10 +124,10 @@ const processNodeUrl = (
if (url[0] === '/' && url[1] !== '/') {
// prefix with base (dev only, base is never relative)
const fullUrl = path.posix.join(devBase, url)
overwriteAttrValue(s, sourceCodeLocation, fullUrl)
if (server && shouldPreTransform(url, config)) {
preTransformRequest(server, fullUrl, devBase)
}
return fullUrl
} else if (
(url[0] === '.' || startsWithWordCharRE.test(url)) &&
originalUrl &&
Expand All @@ -148,11 +148,10 @@ const processNodeUrl = (
// rewrite before `./index.js` -> `localhost:5173/a/index.js`.
// rewrite after `../index.js` -> `localhost:5173/index.js`.

const processedUrl =
attr.name === 'srcset' && attr.prefix === undefined
? processSrcSetSync(url, ({ url }) => replacer(url))
: replacer(url)
overwriteAttrValue(s, sourceCodeLocation, processedUrl)
const processedUrl = useSrcSetReplacer
? processSrcSetSync(url, ({ url }) => replacer(url))
: replacer(url)
return processedUrl
}
}
const devHtmlHook: IndexHtmlTransformHook = async (
Expand Down Expand Up @@ -241,17 +240,39 @@ const devHtmlHook: IndexHtmlTransformHook = async (
const { src, sourceCodeLocation, isModule } = getScriptInfo(node)

if (src) {
processNodeUrl(
src,
sourceCodeLocation!,
s,
const processedUrl = processNodeUrl(
src.value,
isSrcSet(src),
config,
htmlPath,
originalUrl,
server,
)
if (processedUrl) {
overwriteAttrValue(s, sourceCodeLocation!, processedUrl)
}
} else if (isModule && node.childNodes.length) {
addInlineModule(node, 'js')
} else if (node.childNodes.length) {
const scriptNode = node.childNodes[
node.childNodes.length - 1
] as DefaultTreeAdapterMap['textNode']
for (const {
url,
start,
end,
} of extractImportExpressionFromClassicScript(scriptNode)) {
const processedUrl = processNodeUrl(
url,
false,
config,
htmlPath,
originalUrl,
)
if (processedUrl) {
s.update(start, end, processedUrl)
}
}
}
}

Expand Down Expand Up @@ -280,14 +301,20 @@ const devHtmlHook: IndexHtmlTransformHook = async (
for (const p of node.attrs) {
const attrKey = getAttrKey(p)
if (p.value && assetAttrs.includes(attrKey)) {
processNodeUrl(
p,
node.sourceCodeLocation!.attrs![attrKey],
s,
const processedUrl = processNodeUrl(
p.value,
isSrcSet(p),
config,
htmlPath,
originalUrl,
)
if (processedUrl) {
overwriteAttrValue(
s,
node.sourceCodeLocation!.attrs![attrKey],
processedUrl,
)
}
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions playground/vitestSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,10 @@ export async function startDefaultServe(): Promise<void> {
process.env.VITE_INLINE = 'inline-serve'
const testConfig = mergeConfig(options, config || {})
viteServer = server = await (await createServer(testConfig)).listen()
// use resolved port/base from server
const devBase = server.config.base
viteTestUrl = `http://localhost:${server.config.server.port}${
devBase === '/' ? '' : devBase
}`
viteTestUrl = server.resolvedUrls.local[0]
if (server.config.base === '/') {
viteTestUrl = viteTestUrl.replace(/\/$/, '')
}
await page.goto(viteTestUrl)
} else {
process.env.VITE_INLINE = 'inline-build'
Expand Down

0 comments on commit ea47b8f

Please sign in to comment.