0
# Client Runtime
1
2
Core module execution engine that runs transformed JavaScript/TypeScript code with proper context isolation and dependency management. The client runtime is responsible for executing modules in Node.js with Vite's transformation support.
3
4
## Capabilities
5
6
### ViteNodeRunner
7
8
Main runner class for executing modules with Vite's transformation pipeline.
9
10
```typescript { .api }
11
/**
12
* Main runner class for executing modules with proper isolation and context management
13
* Handles module caching, dependency tracking, and execution context preparation
14
*/
15
class ViteNodeRunner {
16
constructor(options: ViteNodeRunnerOptions);
17
18
/** Execute a file by file path */
19
executeFile(file: string): Promise<any>;
20
21
/** Execute a module by its ID */
22
executeId(rawId: string): Promise<any>;
23
24
/** Resolve a URL for a given ID */
25
resolveUrl(id: string, importee?: string): Promise<[url: string, fsPath: string]>;
26
27
/** Check if an ID should be resolved */
28
shouldResolveId(id: string, _importee?: string): boolean;
29
30
/** Check if a module should be interoped */
31
shouldInterop(path: string, mod: any): boolean;
32
33
/** Import a module with interop support */
34
interopedImport(path: string): Promise<any>;
35
36
/** Prepare execution context for a module */
37
prepareContext(context: Record<string, any>): Record<string, any>;
38
39
// Properties
40
root: string;
41
debug: boolean;
42
moduleCache: ModuleCacheMap;
43
}
44
45
interface ViteNodeRunnerOptions {
46
/** Root directory for module resolution */
47
root: string;
48
49
/** Function to fetch and transform modules */
50
fetchModule: FetchFunction;
51
52
/** Optional function to resolve module IDs */
53
resolveId?: ResolveIdFunction;
54
55
/** Optional function to create HMR hot context */
56
createHotContext?: CreateHotContextFunction;
57
58
/** Base URL for module resolution */
59
base?: string;
60
61
/** Module cache instance (optional, will create default if not provided) */
62
moduleCache?: ModuleCacheMap;
63
64
/** Module execution info tracking */
65
moduleExecutionInfo?: ModuleExecutionInfo;
66
67
/** Whether to interop default exports (default: true) */
68
interopDefault?: boolean;
69
70
/** Stub modules for specific request patterns */
71
requestStubs?: Record<string, any>;
72
73
/** Enable debug mode */
74
debug?: boolean;
75
}
76
```
77
78
**Usage Examples:**
79
80
```typescript
81
import { ViteNodeRunner } from "vite-node/client";
82
83
// Basic runner setup
84
const runner = new ViteNodeRunner({
85
root: "/path/to/project",
86
fetchModule: (id) => server.fetchModule(id),
87
resolveId: (id, importer) => server.resolveId(id, importer),
88
});
89
90
// Execute a TypeScript file
91
const result = await runner.executeFile("./src/app.ts");
92
93
// Execute by module ID
94
const moduleResult = await runner.executeId("virtual:my-module");
95
```
96
97
### ModuleCacheMap
98
99
Extended Map for intelligent module caching with dependency tracking and invalidation.
100
101
```typescript { .api }
102
/**
103
* Extended Map for module caching with dependency tracking and smart invalidation
104
* Provides methods for cache management and dependency tree invalidation
105
*/
106
class ModuleCacheMap extends Map<string, ModuleCache> {
107
/** Normalize a file system path for use as cache key */
108
normalizePath(fsPath: string): string;
109
110
/** Update existing cache entry with partial data */
111
update(fsPath: string, mod: ModuleCache): this;
112
113
/** Set cache entry by module ID */
114
setByModuleId(modulePath: string, mod: ModuleCache): this;
115
116
/** Get cache entry by module ID, creating empty entry if not exists */
117
getByModuleId(modulePath: string): ModuleCache & Required<Pick<ModuleCache, 'imports' | 'importers'>>;
118
119
/** Delete cache entry by module ID */
120
deleteByModuleId(modulePath: string): boolean;
121
122
/** Invalidate a single module cache entry */
123
invalidateModule(mod: ModuleCache): boolean;
124
125
/** Invalidate dependency tree upwards (modules that depend on given modules) */
126
invalidateDepTree(ids: string[] | Set<string>, invalidated?: Set<string>): Set<string>;
127
128
/** Invalidate dependency tree downwards (dependencies of given modules) */
129
invalidateSubDepTree(ids: string[] | Set<string>, invalidated?: Set<string>): Set<string>;
130
131
/** Get source map for a module */
132
getSourceMap(id: string): EncodedSourceMap | null;
133
}
134
135
interface ModuleCache {
136
/** Promise for module loading/execution */
137
promise?: Promise<any>;
138
139
/** Exported values from the module */
140
exports?: any;
141
142
/** Whether module has been fully evaluated */
143
evaluated?: boolean;
144
145
/** Whether module is currently being resolved */
146
resolving?: boolean;
147
148
/** Transformed source code */
149
code?: string;
150
151
/** Source map for the module */
152
map?: EncodedSourceMap;
153
154
/** Set of module IDs that import this module */
155
importers?: Set<string>;
156
157
/** Set of module IDs that this module imports */
158
imports?: Set<string>;
159
}
160
```
161
162
**Usage Examples:**
163
164
```typescript
165
import { ModuleCacheMap } from "vite-node/client";
166
167
// Create custom cache
168
const cache = new ModuleCacheMap();
169
170
// Cache a module
171
cache.set("/path/to/module.js", {
172
exports: { default: "value" },
173
evaluated: true,
174
});
175
176
// Invalidate dependency tree
177
const invalidated = cache.invalidateDepTree(["/path/to/changed.js"]);
178
179
// Get source map
180
const map = cache.getSourceMap("/path/to/module.js");
181
```
182
183
### Module Execution Info
184
185
Performance tracking for module execution timing and statistics.
186
187
```typescript { .api }
188
/**
189
* Map tracking execution performance for loaded modules
190
* Provides timing information and self-time calculation
191
*/
192
type ModuleExecutionInfo = Map<string, ModuleExecutionInfoEntry>;
193
194
interface ModuleExecutionInfoEntry {
195
/** Start offset for the module execution */
196
startOffset: number;
197
198
/** The duration that was spent executing the module */
199
duration: number;
200
201
/** The time that was spent executing the module itself and externalized imports */
202
selfTime: number;
203
}
204
```
205
206
### Default Request Stubs
207
208
Default stub modules for common Vite client requests.
209
210
```typescript { .api }
211
/**
212
* Default request stubs for common Vite client modules
213
* Provides mock implementations for client-side dependencies in server environment
214
*/
215
const DEFAULT_REQUEST_STUBS: Record<string, Record<string, unknown>>;
216
```
217
218
**Usage Examples:**
219
220
```typescript
221
import { DEFAULT_REQUEST_STUBS } from "vite-node/client";
222
223
// Use default stubs
224
const runner = new ViteNodeRunner({
225
root: "/project",
226
fetchModule: myFetchFunction,
227
requestStubs: {
228
...DEFAULT_REQUEST_STUBS,
229
"my-custom-stub": { mock: "value" },
230
},
231
});
232
```
233
234
## Error Handling
235
236
The client runtime handles various error conditions:
237
238
- **Module Not Found**: When a module cannot be resolved or loaded
239
- **Circular Dependencies**: Detected and handled gracefully with partial exports
240
- **Syntax Errors**: Transformed code syntax errors with source map support
241
- **Execution Timeouts**: Debug warnings for modules taking too long to load
242
- **Import Resolution**: Detailed error messages for failed module resolution
243
244
Common error handling patterns:
245
246
```typescript
247
try {
248
await runner.executeFile("./problematic-file.ts");
249
} catch (error) {
250
if (error.code === 'ERR_MODULE_NOT_FOUND') {
251
// Handle missing module
252
} else {
253
// Handle other execution errors
254
}
255
}
256
```