Search code examples
javascriptknockout.jsecmascript-6browserifybabeljs

Browserify Babel ES2015 Knockout co-dependent modules


I have created a set of singleton modules which get loaded various knockout components and provide a central "command and control" for their respective functional areas. Let's call them FooModule and BarModule

So a typical Knockout component will have

const ko = require('knockout'),
    FooModule =require('../Singletons/FooModel'),
    BarModule =require('../Singletons/BarModel');

This seems to work well, with each module supporting various observables and functions

The problem is, I need FooModel to require BarModel, and BarModel to require FooModel.

This probably wouldn't matter if it was not a Singleton (e.g. Class), however I can't have a separate class per module per component or I would lose the ability to communicate across the components (each page typically has 3-7 components, some of which are duplicates but with different data)

Currently FooModel requires BarModel and vice versa, but the resultant object is {}, which presumably how Browserify deals with files that require each other

Currently each singleton module equates to:

FooModel...
    const ko = require('knockout');
    const BarModel = require('./BarModel');
    let hiddenVariable = 42 ;
    const FooModel = {
       FooMonitor : ko.observable(false),
       FooFunction : (variable) => { functionFoo(variable) }
    }
    const functionFoo = (variable) => {
        return variable === hiddenVariable ;
    };
    module.export FooModel ;


BarModel...
    const ko = require('knockout');
    const FooModel = require('./FooModel');
    let hiddenVariable = 24 ;
    const BarModel = {
       BarMonitor : ko.observable(false),
       BarFunction : (variable) => { functionBar(variable) }
    }
    const functionBar = (variable) => {
        return variable === hiddenVariable ;
    };
    module.export BarModel ;

Each Knockout component happily requires FooModel & BarModel, but if I add

console.info(BarModel)

In the FooModel Module the browser gets {} (empty object)


Solution

  • If FooModel requires BarModel, BarModel can't requires FooModel. It is a module bundler limitation.

    Browserify will automatically remove not-used dependencies. That's why the module output is only stripped to {} when you start using BarModel from FooModel.

    Incorporating comments from @spender - when you discover circular dependencies it is time to change the architecture. Events are a good way to decouple the models (in this case, using KO.postbox will work fine).