题 使用谷歌托管的jQuery的最佳方式,但回到我在Google上的托管库失败


什么是尝试加载的好方法 谷歌托管的jQuery (或其他谷歌托管的库),但如果谷歌尝试失败,加载我的jQuery副本?

我不是说谷歌是片状的。有些情况下谷歌副本被封锁(例如在伊朗)。

我会设置一个计时器并检查jQuery对象吗?

两份副本的危险是什么?

并不是真的在寻找“只使用谷歌”或“只使用自己的”等答案。我理解这些论点。我也理解用户可能会缓存Google版本。我正在考虑一般的云回退。


编辑:这部分补充......

由于Google建议使用google.load加载ajax库,并在完成后执行回调,我想知道这是否是序列化此问题的关键。

我知道这听起来有点疯狂。我只想弄清楚它是否可以以可靠的方式完成。


更新:jQuery现在托管在微软的CDN上。

http://www.asp.net/ajax/cdn/


983
2018-06-18 17:51


起源


好问题。还有,好警告。太多的SO答案是“不要那样做!”不是:“好的,这是怎么做的。” - Jay Stevens
当然第一个答案是“不要使用谷歌托管版本”。 :-) - Nosredna
当然这是因为如果你想拥有一个严肃的网站,你不要依赖托管你文件的其他人。 - Bryan Migliorisi
@Bryan Migliorisi,我猜Twitter毕竟不是那么严重吗?但是我承认他们在一个月前Google倒闭时遇到了谷歌的问题。 - Ionuț G. Stan
使用Google或不使用JS lib主机的优点是值得的,但它已在其他几个线程中讨论过。我正在寻找关于加载延迟的JS后备的技术答案。 - Nosredna


答案:


你可以像这样实现它:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script>
   window.jQuery || document.write('<script src="/path/to/your/jquery"><\/script>');
</script>

这应该在你的页面中 <head> 任何jQuery就绪事件处理程序都应该在 <body> 避免错误(尽管它不是万无一失的!)。

还有一个原因  使用谷歌托管的jQuery是在某些国家,谷歌的域名被禁止。


774
2018-02-22 18:05



是不是javascript下载阻塞(同步)?因此,双重复印问题对我来说不是问题。 - Matt Sherman
正如Matt Sherman所说,Javascript下载应该已经同步。否则,如果页面试图执行依赖于仅下载了一半的库的内联脚本,或者在没有完全下载和执行库的情况下执行库扩展,则会出现许多问题。这也是Yahoo YSlow建议在页面末尾放置javascript的原因之一;这样它就不会阻止下载其他页面元素(包括样式和图像)。至少,浏览器必须延迟执行才能顺序发生。 - gapple
来自验证器狂热者的小修复:JavaScript中不允许使用字符串'</',因为它可能被误解为脚本标记的末尾(SGML短标记符号)。改为'<'+'/ script>'。干杯, - Boldewyn
这个例子不起作用。 1)如果谷歌ajax库不可用,它必须先失效才能失败。可能还要等一下。在我断开计算机与网络连接的测试中,它只是尝试并尝试过并且没有超时。 2)如果(!jQuery)将抛出错误,因为jQuery没有定义,所以Javascript不知道如何处理它。 - RedWolves
要测试是否加载了jQuery,(!window.jQuery)工作正常,并且短路然后检查类型。 - Jörn Zaefferer


到目前为止,这是最简单,最干净的方法:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="path/to/your/jquery"><\/script>')</script>

328
2018-06-22 01:15



注意:HTML5样板正在使用它 github.com/h5bp/html5-boilerplate/blob/master/index.html - Michael Freeman
这就是为什么我有时会用300多分来滚动答案。 - Ben Lesh
人们继续要求我删除 type="text/javascript" 部分,所以对于为旧浏览器编写html的人,请注意,您现在必须添加它。 - BenjaminRH
@BenjaminRH: type="text/javascript" 在旧浏览器中也是不必要的,因为它们都默认为Javascript。 真 老浏览器看着 language 属性;但即便如此,如果缺少属性,Javascript也是默认值。 - Martijn
@Trojan完全可能,只需堆叠电话。请注意,此时您正在打开新的连接主机,因此HTTP流水线操作可能会更快。 ... <script src="//cdn1.com/jquery.js"></script> <script>window.jQuery || document.write('<script src="//cdn2.com/jquery.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="local/jquery.js"><\/script>')</script> - Tom McKenzie


这似乎对我有用:

<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
// has the google object loaded?
if (window.google && window.google.load) {
    google.load("jquery", "1.3.2");
} else {
    document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
}
window.onload = function() {
    $('#test').css({'border':'2px solid #f00'});
};
</script>
</head>
<body>
    <p id="test">hello jQuery</p>
</body>
</html>

它的工作方式是使用 google 调用的对象 http://www.google.com/jsapi 加载到 window 目的。如果该对象不存在,我们假设对Google的访问失败。如果是这种情况,我们使用加载本地副本 document.write(在这种情况下,我使用自己的服务器,请使用您自己的服务器进行测试)。

我也测试了存在 window.google.load  - 我也可以做一个 typeof 检查事物是否是适当的对象或功能。但我认为这就是诀窍。

这里只是加载逻辑,因为代码突出显示似乎失败,因为我发布了我正在测试的整个HTML页面:

if (window.google && window.google.load) {
    google.load("jquery", "1.3.2");
} else {
    document.write('<script type="text/javascript" src="http://joecrawford.com/jquery-1.3.2.min.js"><\/script>');
}

虽然我必须说,我不确定如果这是您的网站访问者的一个问题,你应该摆弄 Google AJAX Libraries API 一点都不

有趣的事实我最初尝试在各种版本中使用try..catch块,但找不到像这样干净的组合。我有兴趣看到这个想法的其他实现,纯粹作为练习。


73
2018-06-26 20:41



在这种情况下使用google.load有什么好处,而不是像Rony建议的那样直接加载ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?我想加载它会直接捕获已删除库的问题(如果Google停止提供JQuery 1.3.2会怎样)。此外,在获取www.google.com/jsapi之后,Rony的版本会注意到网络问题,尤其是从缓存中加载jsapi时?有人可能需要使用google.load回调来确定(或者可能有一些返回值包含if(..)中的google.load)。 - Arjan
如果正在测试Google.com的存在,可以进行网络呼叫,或者可以检查是否存在“网守”对象。我正在做的是检查谷歌对象及其“加载”功能。如果这两个都失败了,没有谷歌,我需要本地版本。 Rony的版本实际上完全忽略了www.google.com/jsapi网址,所以我不确定你为什么表明它会被提取。 - artlung
最后,所需的只是加载了jquery库。任何Google图书馆都不是必需的。在Rony的回答中,人们确切知道从Google(或缓存)加载是否成功。但在检查“if(window.google && window.google.load)”时,仍未加载jquery库。是否验证了jquery库的实际加载? - Arjan
啊,我看到我是如何引起混乱的。 “在获取www.google.com/jsapi之后,Rony的版本会注意到网络问题”应该更好地解读:“在获取www.google.com/jsapi之后,您的版本没有发现网络问题”。 - Arjan
我们最近转而使用Google作为jQuery主机;如果我们从被阻止的用户那里得到任何错误报告,我将使用您的答案的变体来重构我们的客户端代码。好答案! - Jarrod Dixon♦


如果您的站点上嵌入了modernizr.js,则可以使用内置的yepnope.js异步加载脚本 - 其他jQuery(带回退)。

Modernizr.load([{
    load : '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'
},{
    test : window.jQuery,
    nope : 'path/to/local/jquery-1.7.2.min.js',
    both : ['myscript.js', 'another-script.js'],
    complete : function () {
        MyApp.init();
    }
}]);

这会加载来自Google-cdn的jQuery。然后检查,如果jQuery成功加载。如果不是(“nope”),则加载本地版本。此外,您的个人脚本也会被加载 - “both”表示加载过程与测试结果无关。

当所有加载过程完成后,在“MyApp.init”的情况下执行一个函数。

我个人更喜欢这种异步脚本加载方式。因为我依赖于现代化建设网站时提供的功能测试,所以无论如何我都将它嵌入到网站上。所以实际上没有开销。


30
2018-06-26 17:02



我想你错过了这个问题的重点 - 你将如何从CDN加载moernizr脚本? - George Filippakos
我不建议从CDN加载Modernizr。应该从modernizr.com获得最小的自定义构建。 - Emanuel Kluge
所以此选项获得+16,而其他选项获得的是500/200 +。但这听起来很不错。是否因为依赖Modernizer而不受欢迎?我碰巧在我们的网站上使用了Modernizer,所以如果这比其他答案更好,有人可以让我知道吗?我是JQuery的新手,所以澄清是值得赞赏的。 - redfox05
在答案的时候,这是一个非常好的选择,但截至2015年, yepnope.js 已弃用。看到 stackoverflow.com/questions/33986561/... - Obmerk Kronen
Modernizr的创建是为了像这个问题一样解决问题。 +1 - Carlos Quijano


这里有一些很好的解决方案,但我想进一步了解本地文件。

在Google确实失败的情况下,它应该加载本地源,但服务器上的物理文件可能不一定是最佳选择。我提出这个问题是因为我目前正在实现相同的解决方案,只是我想回到由数据源生成的本地文件。

我的理由是,在跟踪我从Google加载的内容与本地服务器上的内容时,我想要有一些想法。如果我想更改版本,我会希望保持本地副本与我尝试从Google加载的内容同步。在有许多开发人员的环境中,我认为最好的方法是自动执行此过程,以便所有人都必须做的是更改配置文件中的版本号。

这是我提出的理论上应该有效的解决方案:

  • 在应用程序配置文件中,我将存储3件事:库的绝对URL,JavaScript API的URL和版本号
  • 编写一个获取库本身文件内容的类(从app config获取URL),将其存储在我的数据源中,并附上名称和版本号
  • 编写一个处理程序,将我的本地文件从db中拉出并缓存该文件,直到版本号发生变化。
  • 如果它确实发生了变化(在我的应用程序配置中),我的类将根据版本号提取文件内容,将其保存为我的数据源中的新记录,然后处理程序将启动并提供新版本。

理论上,如果我的代码写得正确,我需要做的就是更改我的应用程序配置中的版本号然后中提琴!您有一个自动化的后备解决方案,您无需在服务器上维护物理文件。

每个人都在想什么?也许这有点矫枉过正,但它可能是一种维护AJAX库的优雅方法。

橡子


20
2018-01-28 05:49



如果你正在做所有的工作 只是 对于jQuery,我会说它有点矫枉过正。但是,如果您已经为应用程序的其他部分准备了一些组件(例如,如果您已经从数据库加载脚本),那么它看起来非常好。 - Michael Haren
虽然我不相信这种好处证明了开发时间和复杂性,但是+1是彻底和新颖的。 - Cory House


if (typeof jQuery == 'undefined') {
// or if ( ! window.jQuery)
// or if ( ! 'jQuery' in window)
// or if ( ! window.hasOwnProperty('jQuery'))    

  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = '/libs/jquery.js';

  var scriptHook = document.getElementsByTagName('script')[0];
  scriptHook.parentNode.insertBefore(script, scriptHook);

}

在您尝试从CDN中包含Google副本之后。

在HTML5中,您无需设置 type 属性。

你也可以用......

window.jQuery || document.write('<script src="/libs/jquery.js"><\/script>');

19
2018-01-12 16:42



+1看起来更清洁。在顶部有一个小错字,我无法清除,因为在'undefined'之后它的ery minor两个右括号 - naveen
第一个选项可以避免Chrome警告 [Violation] Avoid using document.write(). - Bob Stein
不幸的是,第一个选项似乎没有加载 同步。第二种选择 不。 - Bob Stein


您可能希望将本地文件用作最后的手段。

似乎现在jQuery自己的CDN不支持https。如果它确实你那么可能想先从那里加载。

所以这是顺序: Google CDN => Microsoft CDN => 你的本地副本。

<!-- load jQuery from Google's CDN -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
<!-- fallback to Microsoft's Ajax CDN -->
<script> window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min.js">\x3C/script>')</script> 
<!-- fallback to local file -->
<script> window.jQuery || document.write('<script src="Assets/jquery-1.8.3.min.js">\x3C/script>')</script> 

8
2018-02-21 16:09



好的+1 ||句法。 - MEMark
真的需要不止一个后备吗?如果两者都处于离线状态,用户将等待超过一分钟才能看到您的网站 - George Filippakos
脚本加载失败不需要1分钟,是吗。 - Edward Olamisan
@ geo1701和爱德华,真的没有必要第三个。即便有一个后备尚未被证实可靠。如果Google API停止运行,我还没有看到任何保证第一次尝试都会失败。我经历了一个案例场景,其中CDN永远不会加载,保持页面不会呈现,如下所述: stevesouders.com/blog/2013/03/18/http-archive-jquery/... - hexalys


有条件地加载最新/遗留的jQuery版本和后备:

<!--[if lt IE 9]>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery-legacy/dist/jquery.min.js">\x3C/script>')</script>
<![endif]-->
<!--[if gte IE 9]><!-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="/public/vendor/jquery/dist/jquery.min.js">\x3C/script>')</script>
<!--<![endif]-->

7
2018-06-19 06:41



这真的需要更多的支持。 - Ascherer
这不是跨浏览器兼容的。 - Josh Habdas
乔希,是的,确实如此。 - neiker


  • 第1步:jQuery无法加载吗? (检查 jQuery 变量)

如何在JavaScript中检查未定义的变量

  • 第2步:动态导入(备份)javascript文件

如何在另一个JavaScript文件中包含JavaScript文件?


5
2018-06-05 09:02





由于谷歌的禁止问题,我更喜欢使用微软的cdn http://www.asp.net/ajaxlibrary/cdn.ashx


5
2017-07-07 10:06





这是对此的一个很好的解释!

还实现加载延迟和超时!

http://happyworm.com/blog/2010/01/28/a-simple-and-robust-cdn-failover-for-jquery-14-in-one-line/


4
2017-10-20 09:36



仅链接答案没有用,被认为是低质量的。考虑将相关位复制到您的答案中,然后将其归于源。 - cale_b
@cale_b你在开玩笑吧?这个答案超过7年,所以这样的评论是没有根据的。 - Stuart.Sklinar
是的,这是一个古老的答案。虽然他们的建议是有效的。仅在其他地方链接的答案是删除的候选者。更多读者: meta.stackoverflow.com/q/8259 - Rob♦
我完全同意,我自己也会提出适当的建议 - 但7年之后它就毫无意义了。它本应该像7年前那样,而不是7年后。 - Stuart.Sklinar
@Stuart.Sklinar - 如果我在7年前见过它,我会有:)我发现自己在这里做了一些研究,并且第一次看到这个。很抱歉让你感到沮丧 - 我认为我们在SO上的工作是网站的管家,有时候意味着评论,编辑或改进旧问题或答案...... - cale_b