使用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无法加载? (检查
jQuery
variables)
如何在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.com与cdnjs.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 – 完美的为来自中国的用户