RequireJS-在require流和内联中加载AMD模块

RequireJS - Loading AMD modules both inside a require flow and inline

本文关键字:加载 AMD 模块 require RequireJS-      更新时间:2023-09-26

考虑一下:

<script src='global.js'></script>
<script src='require.js'></script>
<script>
require(['modular_foo'], function() {
  //do stuff
});

在sideglobal.js中,我们有:

//global.js
$.getScript("modular_bar.js");

其中modular_foo和modular_bar都是匿名定义的AMD模块。使用requireJS,加载类似上面的东西会给你我们最喜欢的错误,不匹配的匿名定义()模块。

为什么会出现这种错误已经很好了(如果你想知道的话,请阅读该页面),但问题是,如果你无法摆脱这种情况怎么办?

我在一个已经建立的平台上工作,该平台正在逐渐迁移到RJS流,目前没有办法同时使用内联遗留脚本(其中一些脚本具有AMD检查以触发define())和我们的requireJS入口点。

在某些情况下,我可以简单地将内联AMD兼容脚本置于加载require.js库之上,但当您需要根据DOM内容异步加载其他内容(modular_bar.js)时,这就不起作用了。我也可以从外部加载到RJS的文件中注释掉所有AMD检查,但这防止了它们与模块化流中加载的文件不兼容。

有没有人有过类似的经历?你是如何融合你的情感来克服这些冲突的?

我没有在生产环境中使用此解决方案的经验,但我花了几天时间研究这个问题,找出了解决它的最佳方法。

您可以使用一个修改后的RequireJS库,该库不允许匿名define的执行(如果它是通过eval传递的)。此外,您可以通过在下面的代码段中删除对name字符串的类型检查来禁止任何define调用。

以下代码段是对RequireJS的修改,如果eval调用它,它将忽略匿名定义。你可以在这个GitHub Gist中找到完全修改过的require.js

该代码依赖于parse-stack库。如果不能在RequireJS之前包含库,我建议将其连接到文件的顶部。

Demo

// This is a snippet of RequireJS
// ...
define = function (name, deps, callback) {
    var node, context;
    // We will allow named modules to be defined by `eval`
    if (!(typeof name == 'string' || name instanceof String))
    {
        var stack = parseStack(new Error());
        // If we find any eval in the stack, do not define the module
        // This is to avoid the "Mismatched anonymous define() module" error
        // Caused by executing an anonymous define without requireJS
        for(var i = 0; i < stack.length; i++)
        {
            if(stack[i].name == "eval")
            {
                return;
            }
        }
    }
    // ...