谈一谈CDN的JS,CSS文件加载出错主域名重试的问题

背景知识

了解这些基础知识之后,我们再来谈谈怎么做

检测css是否加载出错

目前比较靠谱的方案就是检测某一个特定的样式来判断。页面有多个css文件时我们怎么去对应特定样式呢?方法其实很多。

  1. 文件名匹配class
<link rel="stylesheet" type="text/css" href="//8.url.cn/edu/webcourse/index_e84e768.css" />

index_e84e768.css里面有

#_e84e768{display: none;}
  1. link顺序匹配class
<link rel="stylesheet" type="text/css" href="//cdn.xxx.com/css/a.css" />
<link rel="stylesheet" type="text/css" href="//cdn.xxx.com/css/b.css" />

a.css里面有

.__check__css__loaded0 {display: none;}

b.css里面有

.__check__css__loaded1 {display: none;}

通过link的顺序来检测对应的css是否加载出错。

  1. 增加属性<link rel="stylesheet" type="text/css" href="//cdn.xxx.com/css/a.css" data-checkClass="__check__css__loaded0" /> <link rel="stylesheet" type="text/css" href="//cdn.xxx.com/css/b.css" data-checkClass="__check__css__loaded1"/>

第一种方案通常要修改构建工具比较麻烦。这里仅列出第二种方案的代码 仅供参考。

var checkCssLoaded = function(options) {
        var opts = options || {};
        opts.prefix = opts.prefix ||'__check__css__loaded';
        opts.cdnPath = opts.cdnPath || '//8.url.cn/edu/';
        opts.replacePath = opts.replacePath || '//ke.qq.com';
        var links = document.querySelectorAll('link[rel=stylesheet]');
        links.forEach(function(link, index) {
            var div = document.createElement("div");
            div.className = opts.prefix + index;
            div.style.cssText = "position:absolute;height:0;width:0;overflow:hidden";
            document.body.appendChild(div);
            var flag = (window.getComputedStyle ? window.getComputedStyle(div, null).display : div.currentStyle.display) == 'none';
            // console.log(link.href, flag);
            if (!flag) {
                var href = link.href;
                href = href.replace(opts.cdnPath, opts.replacePath);
                link.href = href;
            }
        });
    }
    checkCssLoaded();

代码解释:原理非常简单。css不阻塞js的加载,但是会阻塞js的执行。所以在浏览器里面css和js的执行时保证顺序的。所有只要这段代码在link标签的后面执行就可以直接判断文件是否加载完成。

ps: 这里顺便补充一下让css不阻止页面渲染的方法

<link href="//cdn.xxx.com/css/a.css" rel="stylesheet" media="none" onload="if(media!='all'){media='all';}">

检测js加载是否加载出错

如果你看过 浏览器 CSS/JS 加载能力测试表,那么就很容易知道script标签是会触发onload或者onreadystatechange(ie浏览器)事件的, 前面也提到了css和js的执行时保证顺序的。

那么检测的方案就很容易了

<script type="text/javascript" src="//7.url.cn/edu/webcourse/index_944c80b.js" onreadystatechange="window.__check__js__loaded0=666;" onload="window.__check__js__loaded0=666;"></script>

js加载完成之后就会设置变量为666。然后通过判断这个变量是否为666就可以知道js是否加载完成。 这边也列一下js主域重试的代码,仅供参考, 注意这段代码放的位置。

var checkJSLoaded = function(options) {
            var opts = options || {};
            opts.prefix = opts.prefix ||'__check__js__loaded';
            opts.cdnPath = opts.cdnPath || '//7.url.cn/edu/';
            opts.replacePath = opts.replacePath || '//ke.qq.com';
            var scripts = document.querySelectorAll('script');
            var index = 0;
            scripts.forEach(function(script) {
                var src = script.src;
                if (!src || src.indexOf(opts.cdnPath) === -1) {return;}

                // console.log(src, window[opts.prefix + index]);
                if (window[opts.prefix + index] !== 666) {
                    src = src.replace(opts.cdnPath, opts.replacePath);
                    var js = document.createElement('script');
                    js.type = script.type;
                    js.src = src;
                    js.async = false;
                    script.insertBefore(js, script);
                    script.removeChild(script);
                }

                index++;
            });
        }
        checkJSLoaded();

还有一个高级的api performance.getEntriesByType('resource')可以获取到加载成功的所有资源。 mdn的地址: https://developer.mozilla.org/zh-CN/docs/Web/API/Performance/getEntriesByType , 我们查一下它的兼容情况发现http://caniuse.com/#search=performance Safari, iOS Safari 全线不兼容。所以暂时不予考虑

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Crossin的编程教室

【编程课堂】selenium 祖传爬虫利器

一些网页,比如微博,只有在登录状态才能进行页面的访问,或者对数据有比较复杂的验证和保护,直接通过网络请求进行登录并获取数据就会比较麻烦。这种时候,就该本篇的主角...

27740
来自专栏技术博文

ueditor富文本编辑器 修改框宽度和高度的方法

在使用ueditor的时候,用的textarea <textarea name="content" id="myEditor">这里写这条规则的回复内容</te...

38270
来自专栏Golang语言社区

41. select阻塞一个gorountine上的多个通讯操作 | 厚土Go学习笔记

select 语句可以使得一个 goroutine 在多个通讯操作上等待。select 会阻塞,直到条件分支中的某个分支可以执行,就执行此分支。当多个分支都准备...

38280
来自专栏老马寒门IT

07Vue.js快速入门-Vue路由详解

对于前端来说,其实浏览器配合超级连接就很好的实现了路由功能。但是对于单页面应用来说,浏览器和超级连接的跳转方式已经不能适用, 所以各大框架纷纷给出了单页面应用...

39450
来自专栏Golang语言社区

golang文件传输服务

本篇介绍一个完整的golang文件传输服务器。 完整的代码可以看服务器,客户端 网络使用的框架如上篇介绍,这里就不再复述. 首先定义3个命令码: const (...

38050
来自专栏Java帮帮-微信公众号-技术文章全总结

错误集锦2.jsp页面syntax error,insert“}”to complete block

补:错误集锦1-HttpServlet was not found on the Java Build Path。 我们在用Eclipse进行Java web开...

37640
来自专栏jouypub

优化Vue项目的文件大小

在使用Vue搭建项目时,经常由于引入的库太多,导致打包后的文件体积非常大,特别是vendor.js。这就造成页面第一次打开很慢,如果在浏览器中调试页面(打开控制...

34930
来自专栏更流畅、简洁的软件开发方式

【自然框架】 页面里的父类——把共用的东东都交给父类,让子类专注于其他。

【类图】 ? 【命名空间】——————————————————【文件截图】 ? ? 可能您会问,不就是弄个父类吗,怎么又是这么复杂呢?这个嘛,听...

23680
来自专栏Android自学

给WordPress文章添加类似说说的状态样式

19930
来自专栏九彩拼盘的叨叨叨

CSS拓展语言:Sass介绍

CSS拓展语言出现的原因是,CSS自身支持的功能能有限(如不支持变量,条件控制,循环等编程元素),并不满足我们想要的一些功能。而CSS拓展语言支持CSS不支持的...

11420

扫码关注云+社区

领取腾讯云代金券