Circular dependencies don’t work

It looks like webpack doesn’t have the same behavior as node.js for circular dependencies. When I require a module that closes a dependency loop, it seems to just return an empty object that is never populated. In node.js, an empty object is returned (or actually it might be a partially populated object) that is eventually filled in with all the module’s exports.

Am I just doing something wrong, or does webpack not support node.js-like circular dependencies?

Author: Fantashit

5 thoughts on “Circular dependencies don’t work

  1. Hitting this exact problem currently:

    FileA:
    var b = require file B
    var c = require file C
    
    FileB:
    var a = require file A
    
    FileC:
    var a = require file A
    

    When I run the code, I get an error in File C: A.doSomething is not a function.

    Threw a debugger in there and saw that A is an empty object. What’s really weird is that I’m only getting an error in File C, but not File B. Super confused here.

  2. Have the same issue when I extend one class from another – Uncaught TypeError: Cannot read property 'prototype' of undefined

  3. The worst part of this mess is that i have yet to find a module loader capable of DETECTING a circular dependency and just printing a meaningful error saying “circular dependency”. They all end up failing rather badly and with no hint to what the real problem may be. The “Cannot read property ‘prototype’ of undefined” is just completely unacceptable, for a problem AS COMMON AS a circular dependency. Also detecting a circular ref is a simple thing to do in the loader. It would be like 10 lines of code, which is just building a map and constantly searching it before you add to it.

  4. I actually did find a great solution. The key is that you DO have to BREAK the circular reference at some point in the chain, but there’s a methodical to do it. Just use an interface for one or more of your ‘import’ so that it ‘breaks the circularity’. In my particular app it just so happened that if I remove dialogs objects from the ‘chain’ (using interface imports for those) circularity is solved:

    Project:
    (https://github.com/Clay-Ferguson/meta64)

    Here’s the relevant links to let you piece it together:

    ** Interface to be imported (and won’t cause circular issues)
    https://github.com/Clay-Ferguson/meta64/blob/master/src/main/resources/public/ts/AudioPlayerDlg.ts

    ** Implementation of the Interface
    https://github.com/Clay-Ferguson/meta64/blob/master/src/main/resources/public/ts/AudioPlayerDlgImpl.ts

    ** How I construct these types of objects
    https://github.com/Clay-Ferguson/meta64/blob/master/src/main/resources/public/ts/Factory.ts

    Sorry that I don’t have time to post a full “how to” (but merely those examples). To be clear what I’m saying is if I removed all the similar ‘interfaces’ from my app, and tried to import dialogs directly that creates circularity (and FAILS to load). However, doing what i do on those files i linked above, throughout all my dialogs (loading asynchronously, and importing the INTERFACE instead), was the solution, and solved the circular ref issues.

  5. That error message is basically the equivalent of a null-pointer exception in Java. It just means they didn’t do any error detection whatsoever, and so it just malfunctions ungracefully when it tries to access unset variable. Countless other bugs would cause precisely the same error, and therein lies the problem. They need to print an error that shows not only that it’s a “Circular Ref”, but they ALSO need to show the full stack of module loads (like a call stack) that led up to the circle being encountered. Sounds hard to implement, but in reality is not.

Comments are closed.