perf(plugin): lazily initialize MagicString and remove the redundant pre-check

This commit is contained in:
alex8088 2025-10-19 14:42:35 +08:00
parent c7955aa6fd
commit 0fb8918090
4 changed files with 54 additions and 51 deletions

View File

@ -107,31 +107,27 @@ export default function assetPlugin(): Plugin {
let s: MagicString | undefined
nodeAssetRE.lastIndex = 0
if (code.match(nodeAssetRE)) {
while ((match = nodeAssetRE.exec(code))) {
s ||= new MagicString(code)
const [full, hash] = match
const filename = this.getFileName(hash)
const outputFilepath = toRelativePath(filename, chunk.fileName)
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
while ((match = nodeAssetRE.exec(code))) {
s ||= new MagicString(code)
const [full, hash] = match
const filename = this.getFileName(hash)
const outputFilepath = toRelativePath(filename, chunk.fileName)
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
nodePublicAssetRE.lastIndex = 0
if (code.match(nodePublicAssetRE)) {
while ((match = nodePublicAssetRE.exec(code))) {
s ||= new MagicString(code)
const [full, hash] = match
const filename = publicAssetPathCache.get(hash)!
const outputFilepath = toRelativePath(filename, normalizePath(path.join(outDir, chunk.fileName)))
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
while ((match = nodePublicAssetRE.exec(code))) {
s ||= new MagicString(code)
const [full, hash] = match
const filename = publicAssetPathCache.get(hash)!
const outputFilepath = toRelativePath(filename, normalizePath(path.join(outDir, chunk.fileName)))
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
if (s) {
@ -139,9 +135,9 @@ export default function assetPlugin(): Plugin {
code: s.toString(),
map: sourcemap ? s.generateMap({ hires: 'boundary' }) : null
}
} else {
return null
}
return null
}
}
}

View File

@ -255,17 +255,20 @@ export function bytecodePlugin(options: BytecodeOptions = {}): Plugin | null {
const chunk = output[name]
if (chunk.type === 'chunk') {
let _code = chunk.code
if (bytecodeRE && _code.match(bytecodeRE)) {
if (bytecodeRE) {
let match: RegExpExecArray | null
const s = new MagicString(_code)
let s: MagicString | undefined
while ((match = bytecodeRE.exec(_code))) {
s ||= new MagicString(_code)
const [prefix, chunkName] = match
const len = prefix.length + chunkName.length
s.overwrite(match.index, match.index + len, prefix + chunkName + 'c', {
contentOnly: true
})
}
_code = s.toString()
if (s) {
_code = s.toString()
}
}
if (bytecodeChunks.includes(name)) {
const bytecodeBuffer = await compileToBytecode(_code)

View File

@ -38,20 +38,22 @@ export default function modulePathPlugin(config: InlineConfig): Plugin {
}
},
renderChunk(code, chunk, { sourcemap }): { code: string; map: SourceMapInput } | null {
if (code.match(modulePathRE)) {
let match: RegExpExecArray | null
const s = new MagicString(code)
let match: RegExpExecArray | null
let s: MagicString | undefined
while ((match = modulePathRE.exec(code))) {
const [full, hash] = match
const filename = this.getFileName(hash)
const outputFilepath = toRelativePath(filename, chunk.fileName)
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
modulePathRE.lastIndex = 0
while ((match = modulePathRE.exec(code))) {
s ||= new MagicString(code)
const [full, hash] = match
const filename = this.getFileName(hash)
const outputFilepath = toRelativePath(filename, chunk.fileName)
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
if (s) {
return {
code: s.toString(),
map: sourcemap ? s.generateMap({ hires: 'boundary' }) : null

View File

@ -37,20 +37,22 @@ export default function workerPlugin(): Plugin {
}
},
renderChunk(code, chunk, { sourcemap }): { code: string; map: SourceMapInput } | null {
if (code.match(nodeWorkerAssetUrlRE)) {
let match: RegExpExecArray | null
const s = new MagicString(code)
let match: RegExpExecArray | null
let s: MagicString | undefined
while ((match = nodeWorkerAssetUrlRE.exec(code))) {
const [full, hash] = match
const filename = this.getFileName(hash)
const outputFilepath = toRelativePath(filename, chunk.fileName)
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
nodeWorkerAssetUrlRE.lastIndex = 0
while ((match = nodeWorkerAssetUrlRE.exec(code))) {
s ||= new MagicString(code)
const [full, hash] = match
const filename = this.getFileName(hash)
const outputFilepath = toRelativePath(filename, chunk.fileName)
const replacement = JSON.stringify(outputFilepath)
s.overwrite(match.index, match.index + full.length, replacement, {
contentOnly: true
})
}
if (s) {
return {
code: s.toString(),
map: sourcemap ? s.generateMap({ hires: 'boundary' }) : null