mirror of
https://github.com/alex8088/electron-vite.git
synced 2026-09-11 19:15:41 +08:00
Merge 533d54ad1e43616e02707e88a9bf40680183c2d3 into 608461c04cf74cbf27b47f9916e10e225cbfe8f1
This commit is contained in:
commit
94ddf0c622
@ -6,29 +6,14 @@
|
||||
|
||||
import MagicString from 'magic-string'
|
||||
import type { SourceMapInput } from 'rollup'
|
||||
import type { Plugin } from 'vite'
|
||||
import type { ESTree, Plugin } from 'vite'
|
||||
|
||||
import { supportImportMetaPaths } from '../electron'
|
||||
|
||||
const CJSyntaxRe = /__filename|__dirname|require\(|require\.resolve\(/
|
||||
|
||||
const CJSShim_normal = `
|
||||
// -- CommonJS Shims --
|
||||
import __cjs_url__ from 'node:url';
|
||||
import __cjs_path__ from 'node:path';
|
||||
import __cjs_mod__ from 'node:module';
|
||||
const __filename = __cjs_url__.fileURLToPath(import.meta.url);
|
||||
const __dirname = __cjs_path__.dirname(__filename);
|
||||
const require = __cjs_mod__.createRequire(import.meta.url);
|
||||
`
|
||||
|
||||
const CJSShim_node_20_11 = `
|
||||
// -- CommonJS Shims --
|
||||
import __cjs_mod__ from 'node:module';
|
||||
const __filename = import.meta.filename;
|
||||
const __dirname = import.meta.dirname;
|
||||
const require = __cjs_mod__.createRequire(import.meta.url);
|
||||
`
|
||||
const CJSShimMarker = '// -- CommonJS Shims --'
|
||||
const CJSFilenameRe = /__filename/
|
||||
const CJSDirnameRe = /__dirname/
|
||||
const CJSRequireRe = /require\(|require\.resolve\(/
|
||||
|
||||
const ESMStaticImportRe =
|
||||
/(?<=\s|^|;)import\s*([\s"']*(?<imports>[\p{L}\p{M}\w\t\n\r $*,/{}@.]+)from\s*)?["']\s*(?<specifier>(?<="\s*)[^"]*[^\s"](?=\s*")|(?<='\s*)[^']*[^\s'](?=\s*'))\s*["'][\s;]*/gmu
|
||||
@ -45,19 +30,98 @@ function findStaticImports(code: string): StaticImport[] {
|
||||
return matches
|
||||
}
|
||||
|
||||
export default function esmShimPlugin(): Plugin {
|
||||
const CJSShim = supportImportMetaPaths() ? CJSShim_node_20_11 : CJSShim_normal
|
||||
function addBindingIdentifiers(pattern: ESTree.BindingPattern, bindings: Set<string>): void {
|
||||
if (pattern.type === 'Identifier') {
|
||||
bindings.add(pattern.name)
|
||||
} else if (pattern.type === 'ObjectPattern') {
|
||||
for (const property of pattern.properties) {
|
||||
addBindingIdentifiers(property.type === 'RestElement' ? property.argument : property.value, bindings)
|
||||
}
|
||||
} else if (pattern.type === 'ArrayPattern') {
|
||||
for (const element of pattern.elements) {
|
||||
if (element) addBindingIdentifiers(element.type === 'RestElement' ? element.argument : element, bindings)
|
||||
}
|
||||
} else {
|
||||
addBindingIdentifiers(pattern.left, bindings)
|
||||
}
|
||||
}
|
||||
|
||||
function getUniqueBindingName(base: string, bindings: Set<string>): string {
|
||||
let name = base
|
||||
let index = 1
|
||||
while (bindings.has(name)) name = `${base}${index++}`
|
||||
bindings.add(name)
|
||||
return name
|
||||
}
|
||||
|
||||
function createCJSShim(code: string, bindings: Set<string>): string | null {
|
||||
const needsFilename = !bindings.has('__filename') && CJSFilenameRe.test(code)
|
||||
const needsDirname = !bindings.has('__dirname') && CJSDirnameRe.test(code)
|
||||
const needsRequire = !bindings.has('require') && CJSRequireRe.test(code)
|
||||
|
||||
if (!needsFilename && !needsDirname && !needsRequire) {
|
||||
return null
|
||||
}
|
||||
|
||||
const imports: string[] = []
|
||||
const declarations: string[] = []
|
||||
|
||||
if (supportImportMetaPaths()) {
|
||||
if (needsFilename) declarations.push('const __filename = import.meta.filename;')
|
||||
if (needsDirname) declarations.push('const __dirname = import.meta.dirname;')
|
||||
} else if (needsFilename || needsDirname) {
|
||||
const urlBinding = getUniqueBindingName('__cjs_url__', bindings)
|
||||
imports.push(`import ${urlBinding} from 'node:url';`)
|
||||
if (needsFilename) declarations.push(`const __filename = ${urlBinding}.fileURLToPath(import.meta.url);`)
|
||||
if (needsDirname) {
|
||||
const pathBinding = getUniqueBindingName('__cjs_path__', bindings)
|
||||
imports.push(`import ${pathBinding} from 'node:path';`)
|
||||
declarations.push(`const __dirname = ${pathBinding}.dirname(${urlBinding}.fileURLToPath(import.meta.url));`)
|
||||
}
|
||||
}
|
||||
|
||||
if (needsRequire) {
|
||||
const moduleBinding = getUniqueBindingName('__cjs_mod__', bindings)
|
||||
imports.push(`import ${moduleBinding} from 'node:module';`)
|
||||
declarations.push(`const require = ${moduleBinding}.createRequire(import.meta.url);`)
|
||||
}
|
||||
|
||||
return `\n${CJSShimMarker}\n${imports.join('\n')}\n${declarations.join('\n')}\n`
|
||||
}
|
||||
|
||||
export default function esmShimPlugin(): Plugin {
|
||||
return {
|
||||
name: 'vite:esm-shim',
|
||||
apply: 'build',
|
||||
enforce: 'post',
|
||||
renderChunk(code, _chunk, { format, sourcemap }): { code: string; map?: SourceMapInput } | null {
|
||||
if (format === 'es') {
|
||||
if (code.includes(CJSShim) || !CJSyntaxRe.test(code)) {
|
||||
return null
|
||||
const bindings = new Set<string>()
|
||||
for (const node of this.parse(code).body) {
|
||||
if (node.type === 'ImportDeclaration') {
|
||||
for (const specifier of node.specifiers) {
|
||||
bindings.add(specifier.local.name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
const declaration =
|
||||
node.type === 'ExportNamedDeclaration' || node.type === 'ExportDefaultDeclaration' ? node.declaration : node
|
||||
if (declaration?.type === 'VariableDeclaration') {
|
||||
for (const declarator of declaration.declarations) {
|
||||
addBindingIdentifiers(declarator.id, bindings)
|
||||
}
|
||||
} else if (
|
||||
(declaration?.type === 'FunctionDeclaration' || declaration?.type === 'ClassDeclaration') &&
|
||||
declaration.id
|
||||
) {
|
||||
bindings.add(declaration.id.name)
|
||||
}
|
||||
}
|
||||
|
||||
const CJSShim = createCJSShim(code, bindings)
|
||||
if (!CJSShim) return null
|
||||
|
||||
const lastESMImport = findStaticImports(code).pop()
|
||||
const indexToAppend = lastESMImport ? lastESMImport.end : 0
|
||||
const s = new MagicString(code)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user