@@ -196,6 +196,34 @@ export interface DynamicImportFileOptions {
196196 * @default false
197197 */
198198 bustCache ?: boolean
199+
200+ /**
201+ * Custom import function to use instead of native `import()`.
202+ *
203+ * Useful for bundlers like Vite that provide their own module resolution
204+ * which can handle features Node.js native ESM cannot, such as:
205+ * - Resolving `.js` → `.ts` extensions
206+ * - TypeScript path aliases
207+ * - Virtual modules
208+ *
209+ * @example Vite 5 (ssrLoadModule)
210+ * ```ts
211+ * // In Vite plugin configureServer():
212+ * Mod.dynamicImportFile(path, {
213+ * importFn: (url) => server.ssrLoadModule(url)
214+ * })
215+ * ```
216+ *
217+ * @example Vite 6+ (ModuleRunner)
218+ * ```ts
219+ * // In Vite plugin configureServer():
220+ * const runner = createServerModuleRunner(server.environments.ssr)
221+ * Mod.dynamicImportFile(path, {
222+ * importFn: (url) => runner.import(url)
223+ * })
224+ * ```
225+ */
226+ importFn ?: ( url : string ) => Promise < unknown >
199227}
200228
201229/**
@@ -255,8 +283,13 @@ export const dynamicImportFile = <
255283) : DynamicImportFileResult < $Module , $Options > => {
256284 const importUrl = Fs . Path . toFileUrl ( path )
257285
286+ // Use custom importFn if provided, otherwise native import()
287+ const performImport = options ?. importFn
288+ ? ( ) => options . importFn ! ( importUrl . href )
289+ : ( ) => import ( importUrl . href )
290+
258291 const doImport = Effect . tryPromise ( {
259- try : ( ) => import ( importUrl . href ) ,
292+ try : performImport ,
260293 catch : ( cause ) => createImportError ( path , cause instanceof Error ? cause : new Error ( String ( cause ) ) ) ,
261294 } ) as Effect . Effect < $Module , ImportError >
262295
0 commit comments