构建Javascript模块

时间:2016-10-25 13:16:17

标签: javascript design-patterns dependency-injection

我有用于客户端路由和模板加载的小型库。 它是由几个较小的模块构建的,例如Tpl,Router ..

每个模块检查是否定义了库命名空间,并将其自身应用于它。

以下是代码:https://github.com/sgoran/micro

例如 Tpl 组件将自身绑定到Micro库(主库)

if(typeof Micro === "function" && Micro.prototype.isMicro){
      Micro['Tpl'] = Tpl;

而不是我用构造函数调用库

var micro = new Micro(properties);

问题是,如果我想创建另一个实例......依赖项将在内部发生冲突

var micro2 = new Micro(properties);

对于构建,我使用gulp并将模块连接到一个文件..

有人能提出一个很好的方法来构建多个模块,比如沙箱吗? 或者一些不使用webpack,requireJs等的最佳实践和模式。

3 个答案:

答案 0 :(得分:2)

按原样使用module pattern

// 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); 

如果您不想污染全球范围......

...你可以实现子模块。您将无法完全避免全局范围污染,但您将限制它以声明顶级模块:

// 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继续前进并使用像SystemJS这样的解决方案配置您的模块并避免依赖地狱(否则,您需要手动添加脚本文件并按特定顺序添加依赖模块可用...)。

答案 1 :(得分:1)

您只需摆脱Micro构造函数本身中的所有共享状态。例如,对于me.events = Micro.Pubsub;,所有实例将共享相同的Pubsub实例,这是有问题的,但您可以通过为每个Pubsub实例实例化一个新的Micro来解决这个问题。可能有更多的共享状态(例如document.querySelectorAll('[hub-link]')),但我还没有挖到远。

一旦摆脱了Micro构造函数中的共享状态,虽然使用不同的子模块(例如Tpl,Routes)有多个Micro实例,但仍然存在问题。这是因为您没有使用任何形式的依赖性反转来从Micro构造函数中解析这些子模块。

这可能不是问题,因为我怀疑单个应用程序会同时使用不同的子模块实现。不过,您可能希望将依赖项显式化,并允许将子模块依赖项注入Micro构造函数。

答案 2 :(得分:0)

在不使用任何其他代码(通过CommonJS或AMD工具)的情况下分割应用程序的一个很好的方法就是检查每个子模块的末尾,主模块是否存在..

如果它不存在,我们可以全局公开模块并单独使用它,测试它或类似。

;(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));

**在主模块内声明**

me.tpl = new Micro.Tpl(props);