1
- import fs from 'fs'
2
1
import path from 'path'
2
+ import { Module } from 'module'
3
3
import { ViteDevServer } from '..'
4
- import { cleanUrl , resolveFrom , unwrapId } from '../utils'
4
+ import { unwrapId } from '../utils'
5
5
import { rebindErrorStacktrace , ssrRewriteStacktrace } from './ssrStacktrace'
6
6
import {
7
7
ssrExportAllKey ,
@@ -11,6 +11,8 @@ import {
11
11
ssrDynamicImportKey
12
12
} from './ssrTransform'
13
13
import { transformRequest } from '../server/transformRequest'
14
+ import { InternalResolveOptions , tryNodeResolve } from '../plugins/resolve'
15
+ import { hookNodeResolve } from '../plugins/ssrRequireHook'
14
16
15
17
interface SSRContext {
16
18
global : NodeJS . Global
@@ -80,7 +82,24 @@ async function instantiateModule(
80
82
// referenced before it's been instantiated.
81
83
mod . ssrModule = ssrModule
82
84
83
- const ssrImportMeta = { url }
85
+ const {
86
+ isProduction,
87
+ resolve : { dedupe } ,
88
+ root
89
+ } = server . config
90
+
91
+ const resolveOptions : InternalResolveOptions = {
92
+ conditions : [ 'node' ] ,
93
+ dedupe,
94
+ // Prefer CommonJS modules.
95
+ extensions : [ '.js' , '.mjs' , '.ts' , '.jsx' , '.tsx' , '.json' ] ,
96
+ isBuild : true ,
97
+ isProduction,
98
+ // Disable "module" condition.
99
+ isRequire : true ,
100
+ mainFields : [ 'main' ] ,
101
+ root
102
+ }
84
103
85
104
urlStack = urlStack . concat ( url )
86
105
const isCircular = ( url : string ) => urlStack . includes ( url )
@@ -91,7 +110,7 @@ async function instantiateModule(
91
110
92
111
const ssrImport = async ( dep : string ) => {
93
112
if ( dep [ 0 ] !== '.' && dep [ 0 ] !== '/' ) {
94
- return nodeRequire ( dep , mod . file , server . config . root )
113
+ return nodeRequire ( dep , mod . file , resolveOptions )
95
114
}
96
115
dep = unwrapId ( dep )
97
116
if ( ! isCircular ( dep ) && ! pendingImports . get ( dep ) ?. some ( isCircular ) ) {
@@ -132,6 +151,7 @@ async function instantiateModule(
132
151
}
133
152
}
134
153
154
+ const ssrImportMeta = { url }
135
155
try {
136
156
// eslint-disable-next-line @typescript-eslint/no-empty-function
137
157
const AsyncFunction = async function ( ) { } . constructor as typeof Function
@@ -168,31 +188,38 @@ async function instantiateModule(
168
188
return Object . freeze ( ssrModule )
169
189
}
170
190
171
- function nodeRequire ( id : string , importer : string | null , root : string ) {
172
- const mod = require ( resolve ( id , importer , root ) )
173
- const defaultExport = mod . __esModule ? mod . default : mod
191
+ function nodeRequire (
192
+ id : string ,
193
+ importer : string | null ,
194
+ resolveOptions : InternalResolveOptions
195
+ ) {
196
+ const loadModule = Module . createRequire ( importer || resolveOptions . root + '/' )
197
+ const unhookNodeResolve = hookNodeResolve (
198
+ ( nodeResolve ) => ( id , parent , isMain , options ) => {
199
+ if ( id [ 0 ] === '.' || Module . builtinModules . includes ( id ) ) {
200
+ return nodeResolve ( id , parent , isMain , options )
201
+ }
202
+ const resolved = tryNodeResolve ( id , parent . id , resolveOptions , false )
203
+ if ( ! resolved ) {
204
+ throw Error ( `Cannot find module '${ id } ' imported from '${ parent . id } '` )
205
+ }
206
+ return resolved . id
207
+ }
208
+ )
209
+
210
+ let mod : any
211
+ try {
212
+ mod = loadModule ( id )
213
+ } finally {
214
+ unhookNodeResolve ( )
215
+ }
216
+
174
217
// rollup-style default import interop for cjs
218
+ const defaultExport = mod . __esModule ? mod . default : mod
175
219
return new Proxy ( mod , {
176
220
get ( mod , prop ) {
177
221
if ( prop === 'default' ) return defaultExport
178
222
return mod [ prop ]
179
223
}
180
224
} )
181
225
}
182
-
183
- const resolveCache = new Map < string , string > ( )
184
-
185
- function resolve ( id : string , importer : string | null , root : string ) {
186
- const key = id + importer + root
187
- const cached = resolveCache . get ( key )
188
- if ( cached ) {
189
- return cached
190
- }
191
- const resolveDir =
192
- importer && fs . existsSync ( cleanUrl ( importer ) )
193
- ? path . dirname ( importer )
194
- : root
195
- const resolved = resolveFrom ( id , resolveDir , true )
196
- resolveCache . set ( key , resolved )
197
- return resolved
198
- }
0 commit comments