Browserify仅在多个require调用上执行一次模块代码

时间:2016-02-26 14:55:40

标签: javascript backbone.js marionette browserify commonjs

app.js

var MedicineManager = new Marionette.Application();

MedicineManager.addRegions({
    mainRegion: "#main-region"
});

MedicineManager.navigate = function (route, options) {
    options || (options = {});
    Backbone.history.navigate(route, options);
};

MedicineManager.getCurrentRoute = function () {
    return Backbone.history.fragment;
};

MedicineManager.on("start", function () {
    if (Backbone.history) {
        Backbone.history.start();
    }
});

$(function () {
    MedicineManager.start();
})

module.exports=MedicineManager;

我正在尝试将我的应用程序从Marionette模块模式移动到Browserify。

我在多个文件中调用require('app'),这会导致每次调用require('app')时app.js中的代码都会执行。

因此我收到错误Backbone.history has already been started。 这个问题的解决方案是在初始化时只调用一次代码。

我该如何解决?

1 个答案:

答案 0 :(得分:0)

您不希望将require用于实例化对象。它可以使用,但是经验表明,虽然模块导出应该被缓存,但是有很多实例,当它不存在并且抛出错误时。我发现最好将require用于静态对象/方法。确保单例的最佳方法是在root方法中实例化,然后将实例传递给需要它的模块。

如果要使用require重构现有代码库,可以将实例化对象绑定到全局对象(如window),然后在启动部分中检查此实例该全局对象上的对象并返回它。

module.exports = function () {
    if (!window.__medicineManager){
        var MedicineManager = new Marionette.Application();

        MedicineManager.addRegions({
            mainRegion: "#main-region"
        });

        MedicineManager.navigate = function (route, options) {
            options || (options = {});
            Backbone.history.navigate(route, options);
        };

        MedicineManager.getCurrentRoute = function () {
            return Backbone.history.fragment;
        };

        MedicineManager.on("start", function () {
            if (Backbone.history) {
                Backbone.history.start();
            }
        });

        MedicineManager.start();
        window.__medicineManager = MedicineManager;
    }
    return window.__medicineManager;
}()

更新

顺便说一下,Browerify似乎特别关注这个问题(比CommonJS或WebPack更多)。也许转移到不同的模块系统将为您解决此问题。最终,问题仍然是实例化的模块有点滥用模式。虽然污染全局范围并不理想,但我认为它更接近您想要的单例模式并且将始终有效,无论构建工具的特定模块缓存方法如何。