【问题标题】:Make requireJs not reload jQuery if already on page如果已经在页面上,请让 requireJs 不重新加载 jQuery
【发布时间】:2021-09-10 02:41:29
【问题描述】:

我正在编写一个脚本,该脚本旨在嵌入到第 3 方网站上,以便为其添加功能。我最近删除了我相当混乱的自定义加载程序代码,并开始用 requirejs 替换它。可以选择为我加载的库之一(取决于传入的一些参数)是 jQuery。

这很好用,直到我的脚本包含在 jQuery 已经存在的页面上,在这种情况下,似乎会发生一些插件在加载过程中,requirejs 会在页面的版本上加载 jQuery,并且插件会立即中断。

要求客户重写他们的页面只是为了使用这个脚本是不可能的,所以我想做的是检测 jQuery 是否已经加载,如果是,跳过通过 requirejs 加载它,只使用已经加载一个(当他们使用旧版本的 jQuery 时,这可能会让我遇到奇怪的边缘情况和错误,但我没有太多选择)。

我想我会写一个新模块,首先查看是否加载了 jQuery,如果是,则导出 jQuery 对象,如果不是,则加载它,然后执行导出。但是,我似乎受到了阻碍,因为模块的定义函数似乎需要同步才能工作,所以我不能去加载另一个异步脚本,然后将导出填充到 requirejs 中。

我在文档中遗漏了什么吗?我正在尝试的事情是不可能的吗?

【问题讨论】:

  • 这将解决版本控制问题。但是,这似乎并不能解决插件踩踏问题,因为页面上的版本很可能会在我之前加载,并且没有冲突。我想我可以修改我的服务版本的 jQuery 以不践踏 $/jQuery 对象,并且只是将自己暴露为一个模块,但我宁愿将其作为最后的手段,从那时起我必须记住做到这一点当我更新 jQuery 时改变。
  • 没关系。只有其中一个库需要知道无冲突模式。当您在您的 jQuery 副本上调用 noConflict 时,$jQuery 的值会从加载副本之前恢复为原始值。使用原始实例的插件将继续引用它。原始的 jQuery 实例会假设它是唯一的,这很好。

标签: jquery requirejs


【解决方案1】:

我在一个类似的项目中遇到了同样的问题,将 require.js 用于打算在 3rd 方网站上加载的库。你可以看我的做法here,不过这里是简化版:

// check for existing jQuery
var jQuery = window.jQuery,
    // check for old versions of jQuery
    oldjQuery = jQuery && !!jQuery.fn.jquery.match(/^1\.[0-4](\.|$)/),
    localJqueryPath = libPath + 'jquery/jquery-1.7.2.min',
    paths = {},
    noConflict;

// check for jQuery 
if (!jQuery || oldjQuery) {
    // load if it's not available or doesn't meet min standards
    paths.jquery = localJqueryPath;
    noConflict = !!oldjQuery;
} else {
    // register the current jQuery
    define('jquery', [], function() { return jQuery; });
}

// set up require
require.config({
    paths: paths 
});

// load stuff
require(['jquery', ... ], function($, ...) {

    // deal with jQuery versions if necessary
    if (noConflict) $.noConflict(true);

    // etc

});

如您所见,这会查找 jQuery,然后将“jquery”模块定义为现有库的包装器,或者(如果没有 jQuery 或现有 jQuery 是旧版本)加载库 -带有noConflict的特定jQuery。

这很好用。唯一的缺点是您在脚本中动态调用require(),这使得有效使用r.js 优化器变得更加困难。

【讨论】:

  • 不错的代码。旧的 jQuery 正则表达式不适用于 jQuery >= 1.10。
  • 我在这里有一个类似的问题stackoverflow.com/questions/20291793/…。您如何不使用 API 中建议的map?如果你想为另一个模块加载第三个版本的 jquery,你会怎么做?
【解决方案2】:

我遇到了类似的问题..我的脚本重新加载了 jQuery 两次..使用了 this article 中的 cmets 的解决方案

像魅力一样工作!

(有效的评论是:

“我把它放在我的配置文件中 requirejs.config(...) 之后和之前 requirej(["app"]) 并且成功了")

【讨论】:

  • 好的,但是如果网页没有加载jquery呢?
【解决方案3】:

通过使用 srini 的解决方案,我能够获得一种“条件”方法,仅当网页尚未加载 jquery 时才在 requirejs 中加载它。在我的 main.js 顶部附近(我也在加载角度):

requirejs.config({
    "baseUrl": "./app/",
    "paths": {
        "jquery"            : "https://code.jquery.com/jquery-3.6.0.min.js",
        "angular"           : "https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min"
    },
    "shim": {
        "jquery": {
            "exports" : "$"
        },
        "angular": {
            "exports" : 'angular'
        }
    }
})

// don't load jquery if it is already loaded
if(typeof(jQuery) == 'function') {
    // define 'jquery' so requirejs knows how to get it
    define('jquery', [], function() {
        return jQuery;
    });
} else {
    // require (preload) jquery so it's available in requirejs
    requirejs(['jquery'], function( $ ) {
        return $; // optional
    });
}

我确认了 jquery 的本地副本,其中我在顶部添加了一个“console.log()”,它只被加载一次。我还在我的 html 文件中使用脚本标记进行了测试,没有在服务方法和控制器方法中引用“$”,并且都使用或不使用脚本标记。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 2020-05-06
    • 1970-01-01
    相关资源
    最近更新 更多