如果CDN失败,如何回退到本地样式表(不是脚本)

我链接到CDN上的jQuery Mobile样式表,如果CDN失败,我想回到样式表的本地版本。 对于脚本解决scheme是众所周知的:

<!-- Load jQuery and jQuery mobile with fall back to local server --> <script src="jquery-1.6.3.min.js"></script> <script type="text/javascript"> if (typeof jQuery == 'undefined') { document.write(unescape("%3Cscript src='jquery-1.6.3.min.js'%3E")); } </script> 

我想为样式表做类似的事情:

 <link rel="stylesheet" href="mobile/1.0b3/jquery.mobile-1.0b3.min.css" /> 

我不确定是否可以实现类似的方法,因为我不确定在加载脚本时链接脚本时浏览器是否阻塞(也许可以将样式表加载到脚本标记中,然后注入到页面)?

所以我的问题是:如果CDN失败,如何确保本地加载样式表?

没有跨浏览器testing,但我认为这将工作。 将不得不在你加载jquery之后,或者你将不得不重写在纯JavaScript。

 <script type="text/javascript"> $.each(document.styleSheets, function(i,sheet){ if(sheet.href=='mobile/1.0b3/jquery.mobile-1.0b3.min.css') { var rules = sheet.rules ? sheet.rules : sheet.cssRules; if (rules.length == 0) { $('<link rel="stylesheet" type="text/css" href="path/to/local/jquery.mobile-1.0b3.min.css" />').appendTo('head'); } } }) </script> 

假设你正在使用相同的CDN的CSS和jQuery,为什么不只是做一个testing,并抓住这一切??

 <link href="//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/start/jquery-ui.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script> <script type="text/javascript"> if (typeof jQuery == 'undefined') { document.write(unescape('%3Clink rel="stylesheet" type="text/css" href="../../Content/jquery-ui-1.8.16.custom.css" /%3E')); document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-1.6.4.min.js" %3E%3C/script%3E')); document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-ui-1.8.16.custom.min.js" %3E%3C/script%3E')); } </script> 

我想问题是要检测是否加载样式表。 一种可能的方法如下:

1)在CSS文件的末尾添加一个特殊规则,如:

 #foo { display: none !important; } 

2)在你的HTML中添加相应的div:

 <div id="foo"></div> 

3)准备好文件后,检查#foo是否可见。 如果样式表被加载,它将不可见。

这里演示 – 加载jquery-ui平滑主题; 没有规则被添加到样式表。

这篇文章build议一些解决scheme的引导CSS http://eddmann.com/posts/providing-local-js-and-css-resources-for-cdn-fallbacks/

或者这适用于fontawesome

 <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"> <script> (function($){ var $span = $('<span class="fa" style="display:none"></span>').appendTo('body'); if ($span.css('fontFamily') !== 'FontAwesome' ) { // Fallback Link $('head').append('<link href="/css/font-awesome.min.css" rel="stylesheet">'); } $span.remove(); })(jQuery); </script> 

可能能够在document.styleSheetstesting样式表的存在。

 var rules = []; if (document.styleSheets[1].cssRules) rules = document.styleSheets[i].cssRules else if (document.styleSheets[i].rules) rule= document.styleSheets[i].rules 

testing特定于您正在使用的CSS文件的内容。

这是katy lavallee的答案的扩展。 我已经包装了所有自执行的jQuery语法,以防止可变的冲突,并在dom准备好运行脚本。 我也已经使脚本非特定于一个单一的链接。 IE,现在任何带有“data-fallback”url属性的样式表链接都会被自动parsing。 像以前一样,您不必像以前一样将这些url硬编码到这个脚本中。

http://jsfiddle.net/skibulk/jnfgyrLt/

 <link rel="stylesheet" type="text/css" href="broken-link.css" data-fallback="broken-link2.css"> 

 (function($){ var links = {}; $( "link[data-fallback]" ).each( function( index, link ) { links[link.href] = link; }); $.each( document.styleSheets, function(index, sheet) { if(links[sheet.href]) { var rules = sheet.rules ? sheet.rules : sheet.cssRules; if (rules.length == 0) { link = $(links[sheet.href]); link.attr( 'href', link.attr("data-fallback") ); } } }); })(jQuery); 

你真的想下去这个JavaScript路由加载CSS的情况下,CDN失败?

我没有想到所有的性能影响,但是你将失去对CSS加载时间的控制,并且对于页面加载性能来说,CSS是你想要在HTML之后下载的第一件事情。

为什么不在基础设施级别处理这个问题 – 将自己的域名映射到CDN,给它一个短的TTL,监视CDN上的文件(例如使用Watchmouse或其他),如果CDN失败,则将DNS更改为备份站点。

其他可能有帮助的选项是“永久caching”静态内容,但不能保证浏览器会保留它们或使用应用程序caching。

事实上,正如有人在顶部所说,如果您的CDN不可靠获得一个新的

安迪

看看这些function:

 $.ajax({ url:'CSS URL HERE', type:'HEAD', error: function() { AddLocalCss(); }, success: function() { //file exists } }); 

这里是香草JavaScript版本:

 function UrlExists(url) { var http = new XMLHttpRequest(); http.open('HEAD', url, false); http.send(); return http.status!=404; } if (!UrlExists('CSS URL HERE') { AddLocalCss(); } 

现在的实际function:

 function AddLocalCss(){ document.write('<link rel="stylesheet" type="text/css" href=" LOCAL CSS URL HERE">') } 

只要确保在头部调用AddLocalCss。

您也可以考虑使用本答案中介绍的以下方法之一 :

使用AJAX加载

 $.get(myStylesLocation, function(css) { $('<style type="text/css"></style>') .html(css) .appendTo("head"); }); 

使用dynamic创build的加载

 $('<link rel="stylesheet" type="text/css" href="'+myStylesLocation+'" >') .appendTo("head"); Load using dynamically-created <style> $('<style type="text/css"></style>') .html('@import url("' + myStylesLocation + '")') .appendTo("head"); 

要么

 $('<style type="text/css">@import url("' + myStylesLocation + '")</style>') .appendTo("head"); 

我可能会使用像yepnope.js的东西

 yepnope([{ load: 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js', complete: function () { if (!window.jQuery) { yepnope('local/jquery.min.js'); } } }]); 

从自述中获取。

 //(load your cdn lib here first) <script>window.jQuery || document.write("<script src='//me.com/path/jquery-1.x.min.js'>\x3C/script>")</script>