diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 56e7310602b320..91554dfd34299f 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -103,8 +103,8 @@ test('export * from', async () => { ), ).toMatchInlineSnapshot(` "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"vue\\"); - const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"react\\"); __vite_ssr_exportAll__(__vite_ssr_import_0__); + const __vite_ssr_import_1__ = await __vite_ssr_import__(\\"react\\"); __vite_ssr_exportAll__(__vite_ssr_import_1__);" `) }) @@ -130,20 +130,9 @@ test('export then import minified', async () => { `export * from 'vue';import {createApp} from 'vue';`, ), ).toMatchInlineSnapshot(` - "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');" + "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\\"); + " `) }) @@ -380,8 +369,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() }) {} @@ -402,8 +391,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' } = {} @@ -425,8 +414,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 = {} @@ -468,8 +457,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() { @@ -518,8 +507,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' @@ -550,8 +539,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; @@ -582,8 +571,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' @@ -628,8 +617,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() { @@ -673,15 +662,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_1__ = await __vite_ssr_import__(\\"foo\\"); + "const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"react\\"); + 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 () => { @@ -812,8 +801,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) { @@ -839,8 +828,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]; diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index c5ebdd9ac80f52..996d4411153dc8 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -94,13 +94,11 @@ async function ssrTransformScript( const idToImportMap = new Map() const declaredConst = new Set() - function defineImport(source: string) { + function defineImport(node: Node, source: string) { deps.add(source) const importId = `__vite_ssr_import_${uid++}__` - // 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, + s.appendRight( + node.start, `const ${importId} = await ${ssrImportKey}(${JSON.stringify(source)});\n`, ) return importId @@ -120,8 +118,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( @@ -163,7 +161,7 @@ async function ssrTransformScript( s.remove(node.start, node.end) if (node.source) { // export { foo, bar } from './foo' - const importId = defineImport(node.source.value as string) + const importId = defineImport(node, node.source.value as string) for (const spec of node.specifiers) { defineExport( node.end, @@ -212,7 +210,7 @@ async function ssrTransformScript( // export * from './foo' if (node.type === 'ExportAllDeclaration') { s.remove(node.start, node.end) - const importId = defineImport(node.source.value as string) + const importId = defineImport(node, node.source.value as string) if (node.exported) { defineExport(node.end, node.exported.name, `${importId}`) } else {