Penso che il pezzo critico che ti manca sia che il risultato di   require("foo")    sia  sempre lo stesso oggetto . Considera questo esempio REPL: 
> var myHttpModule = require("http")
{ ... }
> myHttpModule.someNewProperty = "someValue"
'someValue'
> require("http").someNewProperty
'someValue'
 La seconda chiamata a   require("http")    non ha ricreato il modulo   http    - ha convocato il modulo  solo   http    esistente  nell'ambiente di esecuzione corrente di Node, che era stato modificato sulla riga precedente. 
 Quindi, nel tuo esempio, c'è solo un modulo Alpha. Quando Beta e Gamma chiamano   require("alpha")   , ottengono ciascuno lo  stesso  riferimento all'oggetto singleton del modulo Alpha univoco. 
 (O, per essere  perfettamente  precisi, stanno ottenendo lo stesso riferimento al valore   exports    del modulo Alpha.   require     crea  a   Module    object, ma  restituisce  solo la proprietà   exports    di quel modulo. Se al momento non comprendi completamente la distinzione, non è un grosso problema.) 
  Dietro le quinte: cosa succede realmente con   require    nella cache?  
 La prima volta che usi   require    per includere un modulo, il nodo esegue effettivamente il codice in quel modulo. Il modulo risultante è memorizzato in    require.cache    . I successivi tentativi di caricare il modulo con   require    verificano innanzitutto un oggetto modulo già caricato in   require.cache   . ( Nota:  moduli Node integrati nativi dell'ambiente come   http    sono eccezioni in quanto  non  usano   require.cache    - dovrai testare il mio codice qui sotto con un modulo personalizzato.) 
   require.cache    è un oggetto le cui chiavi sono percorso del file del modulo, con valori associati che sono oggetti modulo. Ad esempio, supponiamo che alcuni moduli denominati "   foo   " in   C:\node_modules\foo.js   : 
> require.cache                             // empty cache
{ } 
> require("foo")                            // require foo
{ bar: 'baz' }
> require.cache                             // cache now populated
{ 'C:\node_modules\foo.js':
   { id: 'C: \node_modules\foo.js',
     exports: { bar: 'baz' },
     parent: { ... },
     filename: 'C:\node_modules\foo.js',
     ...
     paths:
      [ ... ] } }
 Il valore corrente del modulo   foo    è in   require.cache["C:\node_modules\foo.js"].exports   . Possiamo utilizzare    require.resolve     per ottenere il percorso del file del modulo dal nome, in modo che possiamo esprimerlo anche come   require.cache[require.resolve("foo")].exports   . 
 Se chiamiamo   require("foo")    una seconda volta, Nodo vede che   require.cache[require.resolve("foo")]    è definito, e quindi restituisce il valore di   require.cache[require.resolve("foo")].exports    invece di rieseguire il codice di creazione del modulo. Questa proprietà   exports    del modulo   foo    in   require.cache    è la singola istanza del valore di esportazione del modulo   foo   , restituita con ogni chiamata successiva a   require("foo")   . 
 Un'implicazione interessante qui è che puoi   delete require.cache[require.resolve("foo")]    per forzare un ricaricamento del modulo   foo    con la prossima chiamata a   require("foo")   , perché l'oggetto che descrive il modulo viene rimosso dall'oggetto   require.cache   . 
  Che cosa significa per me?  
 Senza   require   , puoi ancora condividere valori tra moduli usando le variabili globali. Ad esempio, il tuo caso Alpha / Beta / Gamma funzionerebbe altrettanto bene con solo l'impostazione Beta e Gamma e la lettura del valore globale   global.a   . Invece, con il sistema   require    del nodo, in realtà stai impostando e leggendo   global.require.cache[require.resolve("alpha")].exports.a   , il quale nodo ti consente di leggere esattamente come   require("alpha").a   . 
 Infatti, se vuoi solo condividere un valore e non hai bisogno di importare i tuoi dati condivisi come modulo, potresti anche usare un oggetto namespacing, cioè avere beta e gamma per impostare e leggere le proprietà dell'oggetto% codice%. Il vantaggio principale dell'utilizzo di   global.alpha    è che non è necessario impostare   require    esterno agli altri script, mentre è necessario definire   require("alpha")    prima di   global.alpha = {}    ing Beta e Gamma. (In alternativa, potresti definire in modo condizionale   require    in ogni modulo basato su un controllo   global.alpha   , per vedere se è il primo modulo ad usarlo.)