• ControlJS 让脚本加载的更快


    前端性能的提升大部分都是在脚本加载执行上,ControlJS的出现让我们感觉提高性能如此容易。急不可耐的想把这段时间的研究成果分享出来,希望能给前端俊才们些帮助,同样换回你们的批评指教。非常感谢拔赤师兄的有情支助,让我感觉前端真是个很有乐趣的领域,因为你知道什么是有意义。

    Steve Souders在2010年12月份发布了ControlJS项目,该项目是让开发者更好的去控制javascript文件的下载和执行,是一个可以让脚本加载更快的组件.从而解决了页面加载脚本的性能问题.

    Steve提出了一个非常具有创造性的思想,就是预先异步下载javascript文件而不执行.这一点得到了很多人的关注与验证。Nicholas Zaka也因ControlJS引发了很多思考,并分析了ControlJSLABjs 的区别所在,详细内容可以阅读Thoughts on script loadersSeparating JavaScript download and execution。Zakas不赞成使用额外的脚本加载库,因为Script loader对浏览器检测的依赖,将是高成本的维护,同时浏览器的发展趋势会为我们解决此类问题。

    但是对于中国互联网的特殊性来分析,脚本加载库的应用还是非常有必要的。很多ControlJS的思想让我们合理的应用,提升页面脚本加载性能将是非常显著。Steve专门整理了ControlJS专题,包括一些实例,验证了ControlJS的成功,并使用3篇博闻详细介绍了ControlJS:异步加载延迟执行重写document.write

    1、异步加载

    原理其实很简单:将script的标签type属性值更改为浏览器无法识别的类型,这样浏览器不会认为这是一个脚本,便不会去下载文件。在页面加载时开始读取所有type="text/cjs"的script标签(包括内嵌脚本),如果存在"DATA-CJSSRC"属性将创建IMAGE或者OBJECT对象(依赖浏览器而选择),去异步下载脚本文件并缓存文件,否则便是内嵌脚本需要预存直到需要时使用eval执行,外链需要插入script元素,解析并执行js内容。

    a>增加ControlJS脚本

    var cjsscript = document.createElement('script');
    cjsscript.src = "control.js";
    var cjssib = document.getElementsByTagName('script')[0];
    cjssib.parentNode.insertBefore(cjsscript, cjssib);
    

    b>更改页面脚本标签属性

    <script type="text/cjs" data-cjssrc="main.js"><script>
    
    <script type="text/cjs">
    var name = getName();
    <script>
    

    c>预加载脚本的过程源码内容如下:

    // Download a script as an image.
    // This puts it in the browser's cache, but doesn't execute it.
    CJS.downloadScriptImage = function(url) {
    	var img = new Image();
    	img.src = url;
    };
    
    
    // Download a script as an object.
    // This puts it in the browser's cache, but doesn't execute it.
    // Based on http://www.phpied.com/preload-cssjavascript-without-execution/
    CJS.downloadScriptObject = function(url) {
    	var obj = document.createElement('object');
    	obj.data = url;
    	document.body.appendChild(obj);
    };
    


    2、延迟执行

    预加载javascript文件后,在真正出发交互时在进行脚本的执行操作。

    3、重写document.write

    ControlJS是异步加载所有脚本的,在默认情况下这些异步脚本都是在window.onload解析并执行的,如果此时脚本调用window.write方法,将导致一个不希望发生的问题,就是整个页面被window.write的输出内容替换,所有页面内容将被删除。问题是由于在docuemnt被加载完后调用docuemnt.write方法时将会自动去触发document.open,写入任何处于打开状态的doucment都将会会替换整个页面的内容,这是无可厚非的。

    对于现在被开发者深恶痛绝的广告,一般都是使用document.write方法来呈现内容的,然而无法将这些内容异步处理是开发者非常头疼的问题。

    ControlJS的解决方法便是重写docuemnt.write,执行客户端自定义的方法,便是创建一个dom元素(span),将其插入正在被解析执行的script标签之前,并且设置SPAN的innerHTML的值为docuemnt.write的内容。由于插入innerHTML里存在script标签时,浏览器将不会很好的识别,因此ControlJS的做法是查找并提取出url,并在页面动态创建script对象来执行脚本内容。

    但是ControlJS存在一个bug就是没有考虑到如果document.write中的script脚本中再次出现document.write的时候,将无法正确定位到最初的异步script,导致广告内容输出的位子错位。

    以上便是ControlJS的相关内容,在实际项目的应用中肯定还会存在一些问题,就像Steve说的ControlJS虽然有些处理上牵强些,但它仍然是很有价值的,我们怎样能将别人的思想融入到我们自己的项目中才是最重要的,光靠拿来主义理论是没有任何意义的。

    最后总结ControlJS为我们做了什么事:
    1、异步下载所有脚本
    2、同时处理内嵌与外链脚本
    3、延迟脚本的执行直到页面被渲染完
    4、允许脚本只下载不执行
    5、不改变脚本代码,只是简单改变HTML标签属性
    6、解决了异步脚本中存在docuement.write的问题
    7、ControlJS本身是异步加载

  • 相关阅读:
    LeetCode之“树”:Binary Tree Preorder && Inorder && Postorder Traversal
    LeetCode之“树”:Binary Tree Level Order Traversal && Binary Tree Level Order Traversal II
    LeetCode之“树”:Balanced Binary Tree
    LeetCode之“树”:Sum Root to Leaf Numbers
    LeetCode之“树”:Validate Binary Search Tree
    LeetCode之“树”:Path Sum && Path Sum II
    LeetCode之“树”:Symmetric Tree && Same Tree
    TCP中的MSS解读(转)
    IP协议详解(转)
    TCP 的那些事儿(上)(转)
  • 原文地址:https://www.cnblogs.com/cheche/p/1982706.html
Copyright © 2020-2023  润新知