Search code examples
javascriptcoffeescriptreactjsbrowserify

require (browserify) not working correctly when assigned (empty object), but works when inline


I have the following component definitions in React (coffee jsx):

CompUtils = require './../utils/comp-utils'

...

  render: ->
    console.log CompUtils # prints {} (empty object)
    <div>
      Then
      {CompUtils.getConstructComponent @props.construct, @props.onUpdate, @props.onRemove}
    </div>

But this works:

  render: ->
    console.log require('./../utils/comp-utils')
    <div>
      Then
      {require('./../utils/comp-utils').getConstructComponent @props.construct, @props.onUpdate, @props.onRemove}
    </div>

I am absolutely confounded by this. Note that CompUtils have been used successfully in other components.


Solution

  • Usually when you get an empty object from a require call, it's because you have circular dependencies. So you require A, which requires B, which requires C, which requires A. In that case C will get an empty object representing A, because A hasn't finished exporting its functions/objects yet and A will only be fully available to C on the next tick, when A has finished exporting.

    Here's an example:

    // a.js
    var b = require('./b');
    module.exports = {
      doStuff: function () {
    
      }
    }
    
    // b.js
    var c = require('./c');
    
    // c.js
    var a = require('./a');
    
    // This will fail because a.js hasn't exported doStuff yet, since a required b, which 
    // required c, which required a.
    a.doStuff();
    

    The reason you get an empty object is because Browserify creates an empty object representing module.exports for that module before the module code runs. Which means that another module can require it before it's finished, it's just not fully baked.