Browserify require returns an empty object

我怕爱的太早我们不能终老 提交于 2019-12-04 22:24:03

Since my comment seems to have answered this issue, I thought I'd write it up formally.

When using Require.js you have to think about dependencies between modules. In some sense, this is the same issue as if you weren't using require. Let's pretend you have two files, A.js and B.js, which define an "A" function and a "B" function respectively:

// A.js
window.A = function() {
    // ...
};

// B.js
window.B = function() {
    // ...
};

You can add those files in any order to your page, and your code will work. But what if your definition of "B" depends on the definition of "A":

// B.js
window.B = window.A || function() {
    // ...
};

Now, suddenly order matters: you have to include your B.js file after your A.js file or else B's code won't work. And if your A.js also depends on your B.js ...

// A.js
window.A = window.B || function() {
    // ...
};

Then your code is fatally flawed, because B depends on A and A depends on B, and one has to be defined first. This is what is known as a "circular dependency".

Require has the same problem, only it's easier to miss because Require abstracts a lot of things from you. At the end of the day though Require (being JavaScript code) has to run sequentially, which means it has to define your modules in some order. If your module A depends on module B, and B depends on A, you'll have the same circular dependency issue.

Similarly if you have A that depends on B, and B that depends on C, and C that depends on A, you'll also have a circular dependency. Or if you have a C that depends on D that depends ... well you get the idea. Ultimately any module that depends on any other module has to ensure that neither the dependent module or any of its dependencies depend on the original module.

So how do you fix your code? The obvious way would be to remove the circular dependencies, which will certainly work, but there's also another option. Let's say your A depends on B, but only at run-time, not at load time. In other words instead of:

// A.js
define(['B'], function(B) {
    return B || function() {
        // ...
    };
});

you have:

// A.js
define(['B'], function(B) {
    return function() {
        B();
    };
});

In this case you can use the single argument "synchronous" form of require to avoid having to require "B" at the top of your file:

// A.js
define([], function() {
    return function() {
        var B = require('B');
        B();
    };
});

Because we only use B after we've defined all our modules Require doesn't have to worry about A coming after B; it can define it whenever it wants because, by the time you actually want to use B, it will already be defined. Of course, this assumes that you have some module which actually does include "B" at the top (if you didn't require wouldn't even know that B exists).

Hope that helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!