Skip to content

Commit

Permalink
fix(ssr): hoist import statements to the top (#12274)
Browse files Browse the repository at this point in the history
  • Loading branch information
btea authored Mar 21, 2023
1 parent 2b2ba61 commit 33baff5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 37 deletions.
73 changes: 42 additions & 31 deletions packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ test('export * from', async () => {
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
__vite_ssr_exportAll__(__vite_ssr_import_0__);
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"react\\");
__vite_ssr_exportAll__(__vite_ssr_import_0__);
__vite_ssr_exportAll__(__vite_ssr_import_1__);"
`)
})
Expand All @@ -130,9 +130,20 @@ test('export then import minified', async () => {
`export * from 'vue';import {createApp} from 'vue';`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"vue\\");
__vite_ssr_exportAll__(__vite_ssr_import_1__);const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"vue\\");
__vite_ssr_exportAll__(__vite_ssr_import_1__);"
`)
})

test('hoist import to top', async () => {
expect(
await ssrTransformSimpleCode(
`path.resolve('server.js');import path from 'node:path';`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"node:path\\");
__vite_ssr_import_0__.default.resolve('server.js');"
`)
})

Expand Down Expand Up @@ -369,8 +380,8 @@ function c({ _ = bar() + foo() }) {}
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
const a = ({ _ = __vite_ssr_import_0__.foo() }) => {}
function b({ _ = __vite_ssr_import_0__.bar() }) {}
Expand All @@ -391,8 +402,8 @@ const a = () => {
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
const a = () => {
const { type: n = 'bar' } = {}
Expand All @@ -414,8 +425,8 @@ const foo = {}
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
const foo = {}
Expand Down Expand Up @@ -457,8 +468,8 @@ objRest()
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
function a() {
Expand Down Expand Up @@ -507,8 +518,8 @@ const obj = {
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
const bar = 'bar'
Expand Down Expand Up @@ -539,8 +550,8 @@ class A {
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
const add = __vite_ssr_import_0__.add;
Expand Down Expand Up @@ -571,8 +582,8 @@ class A {
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foo\\");
const bar = 'bar'
Expand Down Expand Up @@ -617,8 +628,8 @@ bbb()
`,
),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\");
function foobar() {
Expand Down Expand Up @@ -662,15 +673,15 @@ test('jsx', async () => {
const result = await transformWithEsbuild(code, id)
expect(await ssrTransformSimpleCode(result.code, '/foo.jsx'))
.toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"react\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"react\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"foo\\");
const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"foo\\");
function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_1__.Foo, null) }) {
return /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_0__.default.Fragment, null, /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(Slot2, null));
}
"
`)
function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_1__.Foo, null) }) {
return /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_0__.default.Fragment, null, /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(Slot2, null));
}
"
`)
})

test('continuous exports', async () => {
Expand Down Expand Up @@ -801,8 +812,8 @@ function test() {
return [foo, bar]
}`),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
function test() {
if (true) {
Expand All @@ -828,8 +839,8 @@ function test() {
return bar;
}`),
).toMatchInlineSnapshot(`
"
const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
"const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\");
function test() {
[__vite_ssr_import_0__.foo];
Expand Down
14 changes: 8 additions & 6 deletions packages/vite/src/node/ssr/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ async function ssrTransformScript(
const idToImportMap = new Map<string, string>()
const declaredConst = new Set<string>()

function defineImport(node: Node, source: string) {
function defineImport(source: string) {
deps.add(source)
const importId = `__vite_ssr_import_${uid++}__`
s.appendRight(
node.start,
// There will be an error if the module is called before it is imported,
// so the module import statement is hoisted to the top
s.appendLeft(
0,
`const ${importId} = await ${ssrImportKey}(${JSON.stringify(source)});\n`,
)
return importId
Expand All @@ -118,8 +120,8 @@ async function ssrTransformScript(
// import { baz } from 'foo' --> baz -> __import_foo__.baz
// import * as ok from 'foo' --> ok -> __import_foo__
if (node.type === 'ImportDeclaration') {
const importId = defineImport(node.source.value as string)
s.remove(node.start, node.end)
const importId = defineImport(node, node.source.value as string)
for (const spec of node.specifiers) {
if (spec.type === 'ImportSpecifier') {
idToImportMap.set(
Expand Down Expand Up @@ -161,7 +163,7 @@ async function ssrTransformScript(
s.remove(node.start, node.end)
if (node.source) {
// export { foo, bar } from './foo'
const importId = defineImport(node, node.source.value as string)
const importId = defineImport(node.source.value as string)
for (const spec of node.specifiers) {
defineExport(
node.end,
Expand Down Expand Up @@ -210,7 +212,7 @@ async function ssrTransformScript(
// export * from './foo'
if (node.type === 'ExportAllDeclaration') {
s.remove(node.start, node.end)
const importId = defineImport(node, node.source.value as string)
const importId = defineImport(node.source.value as string)
if (node.exported) {
defineExport(node.end, node.exported.name, `${importId}`)
} else {
Expand Down

0 comments on commit 33baff5

Please sign in to comment.