Richard_G Richard_G - 1 year ago 112
Javascript Question

Can I break an ES6 JavaScript program using the revealing pattern into separate files?

I have a large and growing JavaScript program that I'd like to break into separate files for maintainability but I don't know if it is possible. I have broken it into modules using the revealing pattern as described here. That helps and it may be all I can logically do.

This is a non-Rails Ruby/Sinatra/Rack middleware/ES6 JavaScript application. I have Sprockets implemented to maintain the asset pipeline. It uses jQuery Mobile Single Page Architecture which is required to maintain an active IoT WebSocket connection. As such, the HTML page and JavaScript function, once loaded, must always be maintained.

A mock-up of the JavaScript is:

$(function ($, window, document) {
let globalTriggered;
const constOne = [1, 2, 3];
const consDot = '.';
$("body").pagecontainer({
defaults: false
});
$(document).on("pagecreate", null, function () {
if (globalTriggered === false) {
globalTriggered = true;

let Module1 = (function () {
let privateMethod1 = function () {
Module2.anotherMethod2()
};
let someMethod1 = function () {
privateMethod1()
};
let anotherMethod1 = function () {
};
return {
someMethod1: someMethod1,
anotherMethod1: anotherMethod1
};
})();
let Module2 = (function () {
let privateMethod2 = function () {
};
let someMethod2 = function () {
Module1.someMethod1();
privateMethod2()
};
let anotherMethod2 = function () {
Module1.anotherMethod1()
};
return {
someMethod2: someMethod2,
anotherMethod2: anotherMethod2
};
})();

} // stabilzer end
}); // pagecreate end
}(window.jQuery, window, document)); // function end


What I would like to do would be to separate modules, like Module1 and Module2 in this example, into their own source files, again for maintainability.

I considered ES6's export/import option, but the import/export must always be done at the top level. Sprocket has a similar restriction in that it stops searching for directives once it hits code. I considered attempting to hack Sprocket past this by using require_self, but that probably won't work and it would be ugly if it did.

Any options? Thanks.

Answer Source

Well, it was nearly as simple as dandavis hinted (thanks). I am just moving the modules into their own file, executing the internal function when they are defined, eliminating their default execution [change their last line from })(); to }()); ], require them at the top using Sprockets (though ES6 export/import should work), and fire them when I need them.

//= require Module1.js
let Module1 = (function () {
    let privateMethod1 = function () {
        Module2.anotherMethod2()
    };
    let someMethod1 = function () {
        privateMethod1()
    };
    let anotherMethod1 = function () {
    };
    return {
        someMethod1: someMethod1,
        anotherMethod1: anotherMethod1
    };
}());
//= require Module2.js
let Module2 = (function () {
    let privateMethod2 = function () {
    };
    let someMethod2 = function () {
        Module1.someMethod1();
        privateMethod2()
    };
    let anotherMethod2 = function () {
        Module1.anotherMethod1()
    };
    return {
        someMethod2: someMethod2,
        anotherMethod2: anotherMethod2
    };
}());
$(function ($, window, document) {
    let globalTriggered;
    const constOne = [1, 2, 3];
    const consDot = '.';
    $("body").pagecontainer({
        defaults: false
    });
    $(document).on("pagecreate", null, function () {
        if (globalTriggered === undefined) {
            globalTriggered = true;

            Module2.anotherMethod2();

        } // stabilzer end
    }()); // pagecreate end
}(window.jQuery, window, document)); // function end

Update: Any callbacks, including functions fired on something like click, must be exposed with the returned associative array and must use the module name in its reference even within that module since the callback will occur externally.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download