在第三方非AMD库中使用AMD定义的模块

时间:2014-11-26 16:19:25

标签: javascript requirejs

我有一个库 - 称之为 SomeLib - 它被定义为支持各种模块加载器:

(function(global, factory) {
    if (typeof define === 'function' && define.amd) {
        define([], factory);
    } else if (typeof module !== 'undefined' && module.exports) {
        module.exports = factory();
    } else {
        global.UriTemplate = factory();
    }
})(this, function() {
   ...
   // returns constructor function
});

我可以使用RequireJS轻松加载它,如

require.config({
  paths: {
    'theLibrary: '../path/to/the/lib'
  }
});

然后我有另一个第三方库 - 称之为 AnotherLib - 它在内部使用SomeLib,如

var the Lib = new SomeLib(...);

这意味着SomeLib必须在全球范围内可用。

AnotherLib只是一个普通的JavaScript模块函数

(function(){
  // the code
})();

它不符合特定的模块加载器。

当我使用RequireJS包含AnotherLib时,我会执行类似

的操作
require.config({
  paths: {
    'theLibrary: '../path/to/the/lib',
    'anotherLib: '../path/to/anotherLib'
  },
  shim: {
     'anotherLib: [
        'theLibrary'
     ]
  }
});

问题是我在AnotherLib中的行上得到一个未定义的异常,它在那里实例化SomeLib(new SomeLib(...))。 这是因为 SomeLib未在全局对象上定义,而是作为AMD模块发布,而AnotherLib并不需要"。

我可以以某种方式解决这个问题,或者AnotherLib是否必须符合AMD标准且正确需要SomeLib。

1 个答案:

答案 0 :(得分:2)

最好的方法是获得符合AMD标准的库或使库符合AMD标准。后一种选择需要手动修改源或具有将非AMD兼容代码转换为真实AMD模块的构建步骤。如何做到这一点取决于库的设计方式。

可以使用任何库的方法是故意将库所需的符号泄漏到全局空间中:

  1. anotherLib依赖于一个新模块,您可以将其称为SomeLib-leak

  2. 创建新模块。此定义不必位于单独的文件中。在打电话给require.config之前,我通常会放置这样的“胶水”模块。该模块将是这样的:

    define('SomeLib-leak', ['SomeLib'], function (SomeLib) {
        window.SomeLib = SomeLib;
    });
    

    我故意在这里define设置模块名称。通常,您不希望调用define设置模块名称,但是对于像上面所示放置的“粘合”模块,这是必要的。

  3. 加载anotherLib时,SomeLibrary将位于全局空间中。