Reputation: 976
I have small library for client side routing and template loading. It's built from several smaller module, for example Tpl, Router..
Every module check if library namespace is defined and than apply itself to it.
Here is the code: https://github.com/sgoran/micro
For example Tpl component binds itself to Micro library (the main lib)
if(typeof Micro === "function" && Micro.prototype.isMicro){
Micro['Tpl'] = Tpl;
And than I am calling library with constructor
var micro = new Micro(properties);
Problem is if I want to make another instance...dependencies will collide internally
var micro2 = new Micro(properties);
For build, I use gulp and just concatenate modules to one file..
Can anyone propose a good way for building multiple modules to one, like sandboxing them? Or some best practices and patterns without using webpack, requireJs etc..
Upvotes: 1
Views: 171
Reputation: 976
A a nice approach for fragmenting application without using any additional code (via CommonJS or AMD tools) would be just to check at the end of each submodule, does a main module exists..
If it does not exist, we can expose module globally and use it individually, test it or similar.
;(function (window, document){
function Tpl(props){
}
Tpl.prototye = {
// some methods
}
if(typeof Micro === "function" && Micro.prototype.isMicro){
Micro['Tpl'] = Tpl;
}
else if ( typeof module != 'undefined' && module.exports ){
module.exports = Tpl;
}else if( typeof define == 'function' && define.amd ){
define( function () { return Tpl; });
}
else{
window.Tpl = Tpl;
}
}(window, document));
**Declaring inside main module **
me.tpl = new Micro.Tpl(props);
Upvotes: 0
Reputation: 64923
Use module pattern as is.
// Module1.js
var Module1 = (function(exports) {
exports.Micro = function() {};
exports.Micro.prototype = {
// Properties...
};
})(Module1 || {});
// Module2.js
var Module2 (function(exports, Module1) {
var micro = new Module1.Micro();
})(exports, Module1);
// Module3.js
var Module3 (function(exports, Module1) {
// No collission here because Module3 creates an isolated scope
// like Module2 already does too!
var micro = new Module1.Micro();
})(exports, Module1);
...you can implement submodules. You won't be able to fully avoid global scope pollution, but you'll limit it to declare the top-level module:
// Module1.js
var Module1 = (function(Module1) {
exports.Micro = function() {};
exports.Micro.prototype = {
// Properties...
};
})(Module1 || {});
// Module2.js
(function(Module1) {
Module1.Module2 = Module1.Module2 || {};
exports.Other = function() {
};
exports.a = 11;
})(Module1 || {});
BTW move forward and go with a solution like SystemJS to configure your modules and avoid the dependency hell (otherwise, you'll need to add your script files manually and in a specific order to let your dependent modules be usable...).
Upvotes: 2
Reputation: 43718
You only have to get rid of all shared state within the Micro
constructor itself. For instance, with me.events = Micro.Pubsub;
all instances will share the same Pubsub
instance which is problematic, but you can solve that by instantiating a new Pubsub
for every Micro
instance. There is probably more shared state (e.g. document.querySelectorAll('[hub-link]')
), but I haven't dug far.
Once you get rid of shared state within the Micro
constructor, what would still be problematic though is to have multiple Micro
instances using different sub-modules (e.g. Tpl, Routes). That is because you did not use any form of dependency inversion to resolve these sub-modules from within the Micro
constructor.
That's probably not a problem though because I doubt a single application would ever use different sub-module implementations concurrently. Still, you may want to make dependencies explicit and allow to inject the sub-modules dependencies into the Micro
constructor.
Upvotes: 1