2015-05-21 18 views
30

Uderzanie dokładnie ten problem, obecnie:okrągłe import z WebPack powrocie pusty obiekt

FileA: 
var b = require file B 
var c = require file C 

FileB: 
var a = require file A 

FileC: 
var a = require file A 

Kiedy uruchomić kod, pojawia się błąd w pliku C:

A.doSomething is not a function 

Threw debuggera tam i zobaczyłem, że A jest pustym obiektem. Co to jest naprawdę dziwne jest to, że dostaję tylko błąd w pliku C, ale nie w pliku B. Super zdezorientowany tutaj.

+0

napisałem narzędzie, aby sprawdzić swój projekt WebPACK okrągłych zależności: https://github.com/DelvarWorld/webpack-cyclic-dependency- checker –

Odpowiedz

58

To nie jest problem związany z pakietami sieci Web, ale właściwość modułów CommonJS.

Gdy najpierw wymagany jest moduł CommonJS, jego właściwość exports jest inicjowana za pustym obiektem za kulisami.

module.exports = {}; 

Moduł może zdecydować o przedłużeniu tego exports własności, ani zastąpić.

exports.namedExport = function() { /* ... */ }; // extends 

module.exports = { namedExport: function() { /* ... */ } }; // overrides 

Więc kiedy A wymaga B i B wymaga A tuż po, A nie jest jeszcze stracony (która będzie produkować nieskończoną pętlę), ale jego obecny exports nieruchomość jest zwracana. Ponieważ A wymagało B na samej górze pliku, przed wyeksportowaniem czegokolwiek, wywołanie require('A') w module B przyniesie pusty obiekt.

Typową poprawką dla zależności cyklicznych jest umieszczenie importu na końcu pliku, po eksportujesz zmienne wymagane przez inne moduły.

A:

module.exports = { foo: 'bar' }; 
require('B'); // at this point A.exports is not empty anymore 

B:

var A = require('A'); 
A.foo === 'bar'; 
+2

To powinna być zaakceptowana odpowiedź. Dzięki ! – Pcriulan

+0

hej ty :) dzięki to pomogło mi zrozumieć problem. Ale co jeśli w A potrzebujesz dostępu do jakiegoś atrybutu wyeksportowanego przez B? W moim codebase po prostu zastąpiłem 'module.exports' przez' exports.attribute' i teraz działa, ale wydaje się niezbyt naturalne –

+0

Zawsze możesz zrobić to samo w B. 'module.exports = {bar: 'foo'} ; var A = require ('a'); ', then' module.exports = {foo: 'bar'}; var B = require ('B'); '. Jeśli twój eksport zależy od siebie, powinieneś budować je stopniowo, rozszerzając eksport zamiast zastępując go. –