11import path from 'node:path'
22import MagicString from 'magic-string'
3- import type { SourceMap } from 'rollup'
3+ import type { RollupAstNode , SourceMap } from 'rollup'
44import type {
55 ExportAllDeclaration ,
66 ExportDefaultDeclaration ,
@@ -99,13 +99,21 @@ async function ssrTransformScript(
9999 const declaredConst = new Set < string > ( )
100100
101101 // hoist at the start of the file, after the hashbang
102- const hoistIndex = hashbangRE . exec ( code ) ?. [ 0 ] . length ?? 0
102+ let hoistIndex = hashbangRE . exec ( code ) ?. [ 0 ] . length ?? 0
103103
104104 function defineImport (
105105 index : number ,
106- source : string ,
106+ importNode : (
107+ | ImportDeclaration
108+ | ( ExportNamedDeclaration & { source : Literal } )
109+ | ExportAllDeclaration
110+ ) & {
111+ start : number
112+ end : number
113+ } ,
107114 metadata ?: DefineImportMetadata ,
108115 ) {
116+ const source = importNode . source . value as string
109117 deps . add ( source )
110118 const importId = `__vite_ssr_import_${ uid ++ } __`
111119
@@ -118,14 +126,23 @@ async function ssrTransformScript(
118126 }
119127 const metadataStr = metadata ? `, ${ JSON . stringify ( metadata ) } ` : ''
120128
121- // There will be an error if the module is called before it is imported,
122- // so the module import statement is hoisted to the top
123- s . appendLeft (
124- index ,
129+ s . update (
130+ importNode . start ,
131+ importNode . end ,
125132 `const ${ importId } = await ${ ssrImportKey } (${ JSON . stringify (
126133 source ,
127134 ) } ${ metadataStr } );\n`,
128135 )
136+
137+ if ( importNode . start === index ) {
138+ // no need to hoist, but update hoistIndex to keep the order
139+ hoistIndex = importNode . end
140+ } else {
141+ // There will be an error if the module is called before it is imported,
142+ // so the module import statement is hoisted to the top
143+ s . move ( importNode . start , importNode . end , index )
144+ }
145+
129146 return importId
130147 }
131148
@@ -137,12 +154,12 @@ async function ssrTransformScript(
137154 )
138155 }
139156
140- const imports : ( ImportDeclaration & { start : number ; end : number } ) [ ] = [ ]
141- const exports : ( (
142- | ExportNamedDeclaration
143- | ExportDefaultDeclaration
144- | ExportAllDeclaration
145- ) & { start : number ; end : number } ) [ ] = [ ]
157+ const imports : RollupAstNode < ImportDeclaration > [ ] = [ ]
158+ const exports : (
159+ | RollupAstNode < ExportNamedDeclaration >
160+ | RollupAstNode < ExportDefaultDeclaration >
161+ | RollupAstNode < ExportAllDeclaration >
162+ ) [ ] = [ ]
146163
147164 for ( const node of ast . body as Node [ ] ) {
148165 if ( node . type === 'ImportDeclaration' ) {
@@ -161,7 +178,7 @@ async function ssrTransformScript(
161178 // import foo from 'foo' --> foo -> __import_foo__.default
162179 // import { baz } from 'foo' --> baz -> __import_foo__.baz
163180 // import * as ok from 'foo' --> ok -> __import_foo__
164- const importId = defineImport ( hoistIndex , node . source . value as string , {
181+ const importId = defineImport ( hoistIndex , node , {
165182 importedNames : node . specifiers
166183 . map ( ( s ) => {
167184 if ( s . type === 'ImportSpecifier' )
@@ -170,7 +187,6 @@ async function ssrTransformScript(
170187 } )
171188 . filter ( isDefined ) ,
172189 } )
173- s . remove ( node . start , node . end )
174190 for ( const spec of node . specifiers ) {
175191 if ( spec . type === 'ImportSpecifier' ) {
176192 if ( spec . imported . type === 'Identifier' ) {
@@ -220,7 +236,7 @@ async function ssrTransformScript(
220236 // export { foo, bar } from './foo'
221237 const importId = defineImport (
222238 node . start ,
223- node . source . value as string ,
239+ node as RollupAstNode < ExportNamedDeclaration & { source : Literal } > ,
224240 {
225241 importedNames : node . specifiers . map (
226242 ( s ) => getIdentifierNameOrLiteralValue ( s . local ) as string ,
@@ -234,13 +250,13 @@ async function ssrTransformScript(
234250
235251 if ( spec . local . type === 'Identifier' ) {
236252 defineExport (
237- node . start ,
253+ node . end ,
238254 exportedAs ,
239255 `${ importId } .${ spec . local . name } ` ,
240256 )
241257 } else {
242258 defineExport (
243- node . start ,
259+ node . end ,
244260 exportedAs ,
245261 `${ importId } [${ JSON . stringify ( spec . local . value as string ) } ]` ,
246262 )
@@ -291,15 +307,14 @@ async function ssrTransformScript(
291307
292308 // export * from './foo'
293309 if ( node . type === 'ExportAllDeclaration' ) {
294- s . remove ( node . start , node . end )
295- const importId = defineImport ( node . start , node . source . value as string )
310+ const importId = defineImport ( node . start , node )
296311 if ( node . exported ) {
297312 const exportedAs = getIdentifierNameOrLiteralValue (
298313 node . exported ,
299314 ) as string
300- defineExport ( node . start , exportedAs , `${ importId } ` )
315+ defineExport ( node . end , exportedAs , `${ importId } ` )
301316 } else {
302- s . appendLeft ( node . start , `${ ssrExportAllKey } (${ importId } );\n` )
317+ s . appendLeft ( node . end , `${ ssrExportAllKey } (${ importId } );\n` )
303318 }
304319 }
305320 }
0 commit comments