使用Google托pipe的jQuery的最佳方式,但是回退到我在Google上的托pipe库失败

尝试在Google (或其他Google托pipe库)上加载托pipejQuery的好方法是什么,但如果Google尝试失败,则加载我的jQuery副本?

我不是说谷歌是片状的。 有些情况下,谷歌的副本被阻止(例如在伊朗显然)。

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

这两份复印件的危险是什么?

没有真正寻找像“只使用Google的”或“只使用自己的”的答案。 我理解这些论点。 我也明白,用户可能已经caching了Google版本。 一般来说,我正在考虑云端的回退。


编辑:这部分添加…

由于Googlebuild议使用google.load加载ajax库,并且在完成时执行callback,所以我想知道这是否是序列化这个问题的关键。

我知道这听起来有点疯狂。 我只是想弄清楚是否可以做到可靠。


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

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

你可以这样做:

<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>以避免错误(尽pipe这不是错误!)。

使用Google托pipe的jQuery的另一个原因是,在一些国家/地区,Google的域名被禁止。

最简单最干净的方法是:

 <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> 

这似乎为我工作:

 <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> 

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

我也testing了window.google.load的存在 – 我也可以做一个types检查,看看事情是适当的对象或函数。 但我认为这是诀窍。

这里只是加载逻辑,因为代码突出显示失败,因为我发布了我正在testing的整个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块,但是找不到像这样干净的组合。 我有兴趣看到这个想法的其他实现,纯粹是一个练习。

如果您的网站上embedded了modernizr.js,则可以使用内置的yepnope.jsasynchronous加载脚本 – 其中包括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(); } }]); 

这从谷歌-cdn加载jquery。 之后检查,如果jquery被成功加载。 如果不是(“nope”),则加载本地版本。 你的个人脚本也被加载 – “both”表示加载过程独立于testing结果。

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

我个人比较喜欢这种asynchronous脚本加载的方式。 而当我build立一个站点时,依靠modernizr提供的functiontesting,我已经将它embedded到网站上了。 所以实际上没有开销。

这里有一些很棒的解决scheme,但是我想就本地文件进一步说明一下。

在Google失败的情况下,它应该加载本地源,但是服务器上的物理文件可能不一定是最好的select。 我提出这一点,因为我目前正在实施相同的解决scheme,只是我想退回到由数据源生成的本地文件。

我之所以这样做,是因为我需要记住从Google加载的内容与我在本地服务器上加载的内容。 如果我想更改版本,我想保持我的本地副本与我试图从Google加载的内容同步。 在一个有很多开发者的环境中,我认为最好的方法是自动化这个过程,所有人只需要在configuration文件中修改一个版本号。

这是我提出的理论解决scheme:

  • 在应用程序configuration文件中,我将存储3件事情:库的绝对url,js api的url以及版本号
  • 编写一个类来获取库本身的文件内容(从应用程序configuration中获取url),将其存储在我的数据源中,名称和版本号
  • 编写一个处理程序,将我的本地文件从数据库中取出并caching文件,直到版本号更改。
  • 如果它改变了(在我的应用程序configuration中),我的类将根据版本号拉取文件内容,将其保存为数据源中的新logging,然后处理程序将启动并提供新版本。

从理论上讲,如果我的代码编写正确,我所需要做的就是改变我的应用程序configuration,然后中提琴的版本号! 你有一个自动化的回退解决scheme,你不必在你的服务器上维护物理文件。

大家怎么想? 也许这是矫枉过正,但它可能是维护你的ajax库的一个优雅的方法。

橡子

 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>'); 

您可能想使用本地文件作为最后的手段。

好像现在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> 

有条件地加载最新/传统的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]--> 

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

  • 第1步:jQuery无法加载? (检查jQueryvariables)

如何在JavaScript中检查未定义的variables

  • 第2步:dynamic导入(备份)JavaScript文件

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

这是一个很好的解释!

还实现加载延迟和超时!

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

对于那些使用ASP.NET MVC 5的人来说,在你的BundleConfig.cs中添加这段代码来启用jQuery的CDN:

 bundles.UseCdn = true; Bundle jqueryBundle = new ScriptBundle("~/bundles/jquery", "//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js").Include("~/Scripts/jquery-{version}.js"); jqueryBundle.CdnFallbackExpression = "window.jQuery"; bundles.Add(jqueryBundle); 

更新:
这个答案结果是错的。 请参阅评论的真实解释。


你们大多数人的问题已经得到解答,但是最后一部分:

这两份复印件的危险是什么?

没有。 你会浪费带宽,可能会添加一些毫秒下载第二个无用的副本,但是如果他们都通过,没有实际的损害。 当然,您应该使用上述技术来避免这种情况。

 if (typeof jQuery == 'undefined')) { ... 

要么

 if(!window.jQuery){ 

如果没有加载cdn版本,将无法正常工作,因为浏览器将运行通过这种情况,并在它仍然下载需要jQuery的JavaScript的其余部分,它会返回错误。 解决scheme是通过该条件加载脚本。

  <script src="http://WRONGPATH.code.jquery.com/jquery-1.4.2.min.js" type="text/javascript"></script><!-- WRONGPATH for test--> <script type="text/javascript"> function loadCDN_or_local(){ if(!window.jQuery){//jQuery not loaded, take a local copy of jQuery and then my scripts var scripts=['local_copy_jquery.js','my_javascripts.js']; for(var i=0;i<scripts.length;i++){ scri=document.getElementsByTagName('head')[0].appendChild(document.createElement('script')); scri.type='text/javascript'; scri.src=scripts[i]; } } else{// jQuery loaded can load my scripts var s=document.getElementsByTagName('head')[0].appendChild(document.createElement('script')); s.type='text/javascript'; s.src='my_javascripts.js'; } } window.onload=function(){loadCDN_or_local();}; </script> 

谷歌托pipe的jQuery

  • 如果你关心的是旧版浏览器,IE9以前的IE版本,这是最广泛兼容的jQuery版本
 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> 
  • 如果你不关心oldIE,这个更小更快:
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 

备份/回退计划!

  • 无论哪种方式,您应该使用回退到本地,以防万一Google CDN失败(不太可能)或阻止您的用户访问您的网站的位置(稍微更可能),如伊朗或有时中国。
 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script>if (!window.jQuery) { document.write('<script src="/path/to/your/jquery"><\/script>'); } </script> 

参考: http : //websitespeedoptimizations.com/ContentDeliveryNetworkPost.aspx

我认为,应该逃避string中的最后<到\ x3C。 当浏览器看到时,它认为这是脚本块的结尾(因为HTMLparsing器不知道JavaScript,它不能区分出现在string中的东西,而是实际上是要结束脚本的东西元件)。 因此,在HTML页面中,从字面上看,会出现(在最好的情况下)导致错误,并且(在最坏的情况下)是一个巨大的安全漏洞。

 <script src="ajax/jquery/jquery-2.0.0.min.js"></script> <script>window.jQuery || document.write('<script src="js/jquery-2.0.0.min.js">\x3C/script>')</script> 

在ASP.NET中使用Razor语法,这段代码提供了后备支持,并使用了一个虚拟根:

 @{var jQueryPath = Url.Content("~/Scripts/jquery-1.7.1.min.js");} <script type="text/javascript"> if (typeof jQuery == 'undefined') document.write(unescape("%3Cscript src='@jQueryPath' type='text/javascript'%3E%3C/script%3E")); </script> 

或者做一个帮手( 帮手概述 ):

 @helper CdnScript(string script, string cdnPath, string test) { @Html.Raw("<script src=\"http://ajax.aspnetcdn.com/" + cdnPath + "/" + script + "\" type=\"text/javascript\"></script>" + "<script type=\"text/javascript\">" + test + " || document.write(unescape(\"%3Cscript src='" + Url.Content("~/Scripts/" + script) + "' type='text/javascript'%3E%3C/script%3E\"));</script>") } 

并像这样使用它:

 @CdnScript("jquery-1.7.1.min.js", "ajax/jQuery", "window.jQuery") @CdnScript("jquery.validate.min.js", "ajax/jquery.validate/1.9", "jQuery.fn.validate") 

我做了一个dynamic加载jQuery,如果它尚未加载,如果源失败,它会继续回退(从许多答案缝合在一起): https : //gist.github.com/tigerhawkvok/9673154

请注意,我计划保持Gist更新,但不是这个答案,它是值得的!

 /* See https://gist.github.com/tigerhawkvok/9673154 for the latest version */ function cascadeJQLoad(i) { // Use alternate CDNs where appropriate to load jQuery if (typeof(i) != "number") i = 0; // the actual paths to your jQuery CDNs var jq_paths = [ "ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js", "ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js" ]; // Paths to your libraries that require jQuery var dependent_libraries = [ "js/c.js" ]; if (window.jQuery === undefined && i < jq_paths.length) { i++; loadJQ(jq_paths[i], i, dependent_libraries); } if (window.jQuery === undefined && i == jq_paths.length) { // jQuery failed to load // Insert your handler here } } /*** * You shouldn't have to modify anything below here ***/ function loadJQ(jq_path, i, libs) { //load jQuery if it isn't already if (typeof(jq_path) == "undefined") return false; if (typeof(i) != "number") i = 1; var loadNextJQ = function() { var src = 'https:' == location.protocol ? 'https' : 'http'; var script_url = src + '://' + jq_path; loadJS(script_url, function() { if (window.jQuery === undefined) cascadeJQLoad(i); }); } window.onload = function() { if (window.jQuery === undefined) loadNextJQ(); else { // Load libraries that rely on jQuery if (typeof(libs) == "object") { $.each(libs, function() { loadJS(this.toString()); }); } } } if (i > 0) loadNextJQ(); } function loadJS(src, callback) { var s = document.createElement('script'); s.src = src; s.async = true; s.onreadystatechange = s.onload = function() { var state = s.readyState; try { if (!callback.done && (!state || /loaded|complete/.test(state))) { callback.done = true; callback(); } } catch (e) { // do nothing, no callback function passed } }; s.onerror = function() { try { if (!callback.done) { callback.done = true; callback(); } } catch (e) { // do nothing, no callback function passed } } document.getElementsByTagName('head')[0].appendChild(s); } /* * The part that actually calls above */ if (window.readyState) { //older microsoft browsers window.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded') { cascadeJQLoad(); } } } else { //modern browsers cascadeJQLoad(); } 

尽pipe为jQuery退避写入document.write("<script></script>")似乎更容易,但Chrome在这种情况下给出了validation错误。 所以我宁愿打破“脚本”一词。 所以它变得像上面更安全。

 <script src="jquery-1.11.1.min.js"></script> <script>if (typeof jQuery === "undefined") { window.jqFallback = true; document.write("<scr"+"ipt src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js'></scr"+"ipt>"); } </script> 

对于长期问题,最好loggingJQuery后备。 在上面的代码中,如果第一个CDN不可用,则从另一个CDN加载JQuery。 但是你可能想知道错误的CDN并永久删除它。 (这种情况是非常特殊的情况)也是更好的日志后备问题。 所以你可以用AJAX发送错误的案例。 由于没有定义JQuery,你应该使用vanilla javascript来进行AJAX请求。

 <script type="text/javascript"> if (typeof jQuery === 'undefined' || window.jqFallback == true) { // XMLHttpRequest for IE7+, Firefox, Chrome, Opera, Safari // ActiveXObject for IE6, IE5 var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); var url = window.jqFallback == true ? "/yourUrl/" : "/yourUrl2/"; xmlhttp.open("POST", url, true); xmlhttp.send(); } </script> 

难以从无法控制的外部数据存储加载资源。 寻找缺失的function是完全错误的,作为避免超时的手段,如下所述: http : //www.tech-101.com/support/topic/4499-issues-using-a-cdn/

另一个替代ajax.googleapis.comcdnjs.cloudflare.com回退:

 (function (doc, $) { 'use strict'; if (typeof $ === 'undefined') { var script = doc.querySelector('script[src*="jquery.min.js"]'), src = script.src.replace('ajax.googleapis.com', 'cdnjs.cloudflare.com'); script.parentNode.removeChild(script); doc.write('<script src="' + src + '"></script>'); } })(document, window.jQuery || window.Zepto); 
  • 你不必关心jQuery版本
  • 完美的资产pipe理,不会与HTML剪辑一起工作
  • 在野外testing – 完美的为来自中国的用户