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

2022-02-28 00:00:00 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
})();

它与特定的模块加载器不兼容。

当我将AnotherLib包含在RequireJS中时,我会执行如下操作

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

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

我是否可以以某种方式解决此问题,或者AnotherLib是否必须符合AMD并正确要求SomeLib。

AMD

最好的方法是获得一个符合推荐答案的库,或者使该库符合amd。后一种选择需要手动修改源代码,或者执行一个构建步骤,将不符合AMD的代码转换为真正的AMD模块。如何执行此操作取决于库的设计方式。

适用于任何库的一种方法是故意将库需要的符号泄漏到全局空间:

  1. 使anotherLib依赖于可以称为SomeLib-leak的新模块。

  2. 创建新模块。此定义不必位于单独的文件中。我通常在调用require.config之前放置这样的"粘合"模块。该模块将如下所示:

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

    我确实特意让define在这里设置了模块名称。通常,您不希望调用hasdefine设置模块名称,但是对于像我上面指出的那样放置的"粘合"模块,这是必要的。

    /li>

加载anotherLib时,SomeLibrary将进入全局空间。

相关文章