In my current project I got now a lot of circular requirement and it starts to become more and more complicated to simply "make sure to plan accordingly" as the manual says nonchalantly.
First issue is backtraces in case requirements go wrong due to circles, the backtrace only shows the current module loaded, not the the lines of requires where another module loading was interrupted by a require. If that was visible fixing that planning may be easier in more complicated cases.
Second, I'd really wish there was a debug flag to node, that writes all requires and when it is forced to return an empty ahead object instead of the executed exports value due to circle.
Third, my main suggestion that would help alot is an optional "options" parameter to require, where I can say, if the required module needs to be executed since some values are going to be used right ahead in the current run-to-end iteration of the requiring module. Or if that module is very happy to get an empty ahead object that is going to be the module.exports once that required module is going to be executed. Thats actually pretty often the case that module is in the current run-to-end iteration just needed as upvalue for any functions that are going to be called after it ran through. In that case require never needs to pause the current run-to-end and can stack the required module to executed once it is done.
require( 'circle.js', { load : 'ahead' } ); // require will never halt the current run-to-end iteration to execute circle.js module, if it happened to be already loaded it will return the loaded one otherwise the empty ahead object.
require( 'circle.js', { load: 'now' } ); // require will never return an empty ahead object. Since that calling module says it knows it will be using the module right away. In case there is a circle, it will throw an Error.
And yes I already fixed a lot of stuff, like not setting module.exports = something; like I did in my naive first implementation, but rather do "func.prototype = module.exports" now. And one particular nasty case I had to work around with vm.runInNewContext( , /* some context I prepared with custom require */ ); to resolve the circle. However, above suggestions would IMO greatly improve heaving to deal with more cross-requiring code to load up properly.