@@ -16,6 +16,7 @@ import {
1616} from './miniflare-options' ;
1717import {
1818 getNodeCompatAliases ,
19+ getNodeCompatExternals ,
1920 injectGlobalCode ,
2021 isNodeCompat ,
2122 resolveNodeAliases ,
@@ -101,6 +102,10 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin {
101102 } ,
102103 configResolved ( config ) {
103104 addNodeBuiltinsToWorkerEnvironmentsIfNeeded ( config , resolvedPluginConfig ) ;
105+ addBuildNodeExternalsToWorkerEnvironmentsIfNeeded (
106+ config ,
107+ resolvedPluginConfig ,
108+ ) ;
104109 } ,
105110 configEnvironment ( name , options ) {
106111 if ( resolvedPluginConfig . type === 'workers' ) {
@@ -327,3 +332,81 @@ function addNodeBuiltinsToWorkerEnvironmentsIfNeeded(
327332 ) ;
328333 }
329334}
335+
336+ /**
337+ * Adds to the worker resolved configuration the necessary node external modules config options if the worker is under nodejs compat
338+ * (this config is under `build.rollupOptions.externals`)
339+ *
340+ * Note: this includes polyfill methods as well as nodejs builtins (given the `resolve.builtins` option maybe externals here should
341+ * not include such modules...?)
342+ *
343+ * @param resolvedConfig the vite resolved config (that will be side-effectfully updated)
344+ * @param name the name of the worker
345+ * @param resolvedPluginConfig the normalized/resolved plugin config
346+ */
347+ function addBuildNodeExternalsToWorkerEnvironmentsIfNeeded (
348+ resolvedConfig : vite . ResolvedConfig ,
349+ resolvedPluginConfig : ResolvedPluginConfig ,
350+ ) {
351+ if ( resolvedPluginConfig . type === 'workers' ) {
352+ Object . entries ( resolvedPluginConfig . workers ) . map (
353+ ( [ environmentName , workerConfig ] ) => {
354+ invariant (
355+ resolvedConfig . environments [ environmentName ] ,
356+ `environment with name "${ environmentName } " not found` ,
357+ ) ;
358+
359+ const nodeCompat = isNodeCompat ( workerConfig ) ;
360+
361+ if ( ! nodeCompat ) {
362+ return ;
363+ }
364+
365+ const nodeCompatExternals = [ ...getNodeCompatExternals ( ) ] ;
366+
367+ const existingExternalOption =
368+ resolvedConfig . environments [ environmentName ] . build . rollupOptions
369+ . external ;
370+ if ( ! existingExternalOption ) {
371+ resolvedConfig . environments [
372+ environmentName
373+ ] . build . rollupOptions . external = [ ...nodeCompatExternals ] ;
374+ return ;
375+ }
376+
377+ if ( typeof existingExternalOption !== 'function' ) {
378+ const existingExternals = Array . isArray ( existingExternalOption )
379+ ? existingExternalOption
380+ : [ existingExternalOption ] ;
381+ resolvedConfig . environments [
382+ environmentName
383+ ] . build . rollupOptions . external = [
384+ ...nodeCompatExternals ,
385+ ...existingExternals ,
386+ ] ;
387+ return ;
388+ }
389+
390+ const nodeCompatExternalsSet = new Set ( nodeCompatExternals ) ;
391+
392+ resolvedConfig . environments [
393+ environmentName
394+ ] . build . rollupOptions . external = (
395+ source : string ,
396+ importer : string | undefined ,
397+ isResolved : boolean ,
398+ ) => {
399+ const existingOptionResult = existingExternalOption (
400+ source ,
401+ importer ,
402+ isResolved ,
403+ ) ;
404+ if ( existingOptionResult ) {
405+ return existingOptionResult ;
406+ }
407+ return nodeCompatExternalsSet . has ( source ) ;
408+ } ;
409+ } ,
410+ ) ;
411+ }
412+ }
0 commit comments