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

perf(ssr): do a single-pass over AST with node cache arrays #17812

Merged
merged 3 commits into from
Aug 3, 2024
Merged
Changes from 1 commit
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
86 changes: 50 additions & 36 deletions packages/vite/src/node/ssr/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,53 +130,67 @@ async function ssrTransformScript(
)
}

// 1. check all import statements and record id -> importName map
// Temporary reference allocations
const imports = []
const exports = []
Eckhardt-D marked this conversation as resolved.
Show resolved Hide resolved

for (const node of ast.body as Node[]) {
if (node.type === 'ImportDeclaration') {
imports.push(node)
} else if (node.type.startsWith('Export')) {
exports.push(node)
}
}

// 1. check all import statements and record id -> importName map
// and deallocate the imports array
while (imports.length > 0) {
const node = imports.shift()!
Eckhardt-D marked this conversation as resolved.
Show resolved Hide resolved
// import foo from 'foo' --> foo -> __import_foo__.default
// import { baz } from 'foo' --> baz -> __import_foo__.baz
// import * as ok from 'foo' --> ok -> __import_foo__
if (node.type === 'ImportDeclaration') {
const importId = defineImport(hoistIndex, node.source.value as string, {
importedNames: node.specifiers
.map((s) => {
if (s.type === 'ImportSpecifier')
return s.imported.type === 'Identifier'
? s.imported.name
: // @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet
s.imported.value
else if (s.type === 'ImportDefaultSpecifier') return 'default'
})
.filter(isDefined),
})
s.remove(node.start, node.end)
for (const spec of node.specifiers) {
if (spec.type === 'ImportSpecifier') {
if (spec.imported.type === 'Identifier') {
idToImportMap.set(
spec.local.name,
`${importId}.${spec.imported.name}`,
)
} else {
idToImportMap.set(
spec.local.name,
`${importId}[${
// @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet
JSON.stringify(spec.imported.value)
}]`,
)
}
} else if (spec.type === 'ImportDefaultSpecifier') {
idToImportMap.set(spec.local.name, `${importId}.default`)
const importId = defineImport(hoistIndex, node.source.value as string, {
importedNames: node.specifiers
.map((s) => {
if (s.type === 'ImportSpecifier')
return s.imported.type === 'Identifier'
? s.imported.name
: // @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet
s.imported.value
else if (s.type === 'ImportDefaultSpecifier') return 'default'
})
.filter(isDefined),
})
s.remove(node.start, node.end)
for (const spec of node.specifiers) {
if (spec.type === 'ImportSpecifier') {
if (spec.imported.type === 'Identifier') {
idToImportMap.set(
spec.local.name,
`${importId}.${spec.imported.name}`,
)
} else {
// namespace specifier
idToImportMap.set(spec.local.name, importId)
idToImportMap.set(
spec.local.name,
`${importId}[${
// @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet
JSON.stringify(spec.imported.value)
}]`,
)
}
} else if (spec.type === 'ImportDefaultSpecifier') {
idToImportMap.set(spec.local.name, `${importId}.default`)
} else {
// namespace specifier
idToImportMap.set(spec.local.name, importId)
}
}
}

// 2. check all export statements and define exports
for (const node of ast.body as Node[]) {
// and deallocate the exports array
while (exports.length > 0) {
const node = exports.shift()!
// named exports
if (node.type === 'ExportNamedDeclaration') {
if (node.declaration) {
Expand Down