浏览器化只执行一次模块代码,在多个需要调用上

Browserify execute a module code only once , on multiple require calls

本文关键字:调用 代码 模块 执行 一次 浏览器      更新时间:2023-09-26

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;

我正在尝试将我的应用程序从木偶模块模式移动到浏览器化。

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

正因为如此,我得到的错误Backbone.history has already been started.此问题的解决方案是在初始化时仅调用一次代码。

我该如何解决?

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

如果要使用 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更严重)。 也许迁移到不同的模块系统将为您解决此问题。 最终,问题仍然是实例化模块对模式的滥用。 虽然污染全局范围并不理想,但我认为它更接近您想要的单例模式,并且无论构建工具的特定模块缓存方法如何,它都将始终有效。