03月24, 2012

chrome扩展对页面性能的影响

chrome一直是高性能著称,并且市场占有率也越来越大。同时扩展功能也带来了很大的便利,但也发现用户安装的扩展可能会对页面的性能有影响。本文讨论下chrome扩展如何影响页面的性能以及一些解决办法。

百度新首页实例

下面我们对照看下没有安装任何扩展的chrome和安装了一些chrome扩展后访问百度新首页的瀑布流。

这是没有安装任何chrome扩展的瀑布流,效果还是非常不错的。

下面我们一些常用的chrome扩展,如:adblock, 音乐电台,截图,lastpass, 代理等,如:

安装了这些扩展后,我们在看下现在的瀑布流是什么样的:

从这个瀑布流里可以看到,中间有很多断的地方,直接导致了加载时间要长很多。

原因分析

那是为啥装了些扩展后就会页面的加载速度呢?

熟悉chrome扩展开发的同学应该知道,chrome扩展是允许向页面里植入CSS和JS的,并且CSS和JS的植入可能还会引起一些图片等资源的下载。

具体的配置在manifest.json里的Content Scripts,如:

"content_scripts": [
 {
     "matches": ["http://www.google.com/*"],
     "css": ["mystyles.css"],
     "js": ["jquery.js", "myscript.js"],
     "run_at": "document_end"
 }
 ]

这个表示向 http://www.google.com/ 下所有页面植入mystyles.css和jquery.js和myscript.js这3个文件,并且植入时段是在document_end。run_at有3个属性值,分别对应:

  • document_start 在页面CSS加载完成之后,DOM结构构造完成和Script执行之前加载
  • document_end 在DOM结构完成之后,图片或者iframe等资源之前
  • document_idle 在document_end和window.onload找个空闲时候触发 从3个run_at值来看,如果植入的脚本在document_start,那对页面的影响是非常大的。虽然这些资源在本地,没什么网络传输时间,但还是有解析和执行时间。

并且一个扩展可以植入多个资源或者脚本,如果扩展安装比较多的话,对页面性能的影响就非常大了。

如何知道用户安装了哪些扩展

当然获取用户安装了哪些扩展会侵犯了用户的隐私,但如果知道用户装了哪些扩展,并且知道这些扩展植入了哪些资源,那对分析页面性能的影响帮助还是非常大的。

如果你去chrome webstore里安装扩展的话,细心的你会发现webstore是知道哪些扩展是安装了的。如图:

通过分析页面里的JS发现,是使用了chrome.*的API进行的,这个API就是chrome浏览器暴露给扩展的API。

https://chrome.google.com/webstore/search/%E7%94%B5%E5%8F%B0页面的Console里,执行chrome,发现chrome有如下的属性和方法:

但在其他非chrome.google.com的域名下执行chrome,只有下面的属性和方法:

也就是说chrome.*下的很多API只给chrome.google.com开了白名单。

那有没有其他办法拿到用户装了哪些扩展呢?

波兰安全研究员Krzysztof Kotowicz通过一个简单粗暴可依赖的办法,只要很短的JS代码就能知道用户安装了哪些扩展,见测试DEMO页,代码如下:

var detect = function(base, if_installed, if_not_installed) {
    var s = document.createElement('script');
    s.onerror = if_not_installed;
    s.onload = if_installed;
    document.body.appendChild(s);
    s.src = base + '/manifest.json';
}
var log = function(msg) {
    document.getElementById('log').value += '[*] ' + msg + '\n';
}

function logme(i, id) {
    return function() {
        log('Detected addon: ' + i + ' (' + id + ')');
    }
}

window.onload = function() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'addons.json', false);
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
         var addons = JSON.parse(xhr.responseText);
         for (var i in addons) {
            if (addons.hasOwnProperty(i)) {
                detect('chrome-extension://' + i,logme(addons[i], i));
            }
         }

      }
    }
    xhr.send(null);
}

实现原理看懂了其实比较简单,通过下面几个步骤: 1、手工维护一个manifest.json,这个文件列举了webstore下扩展列表。当然webstore如果有扩展添加的话,需要手工更新这个列表

2、循环执行manifest.json这个列表,因为每个扩展都有manifest.json这个文件,所以通过script方法加载这个manifest.json文件,地址为:chrome-extention://扩展id/manifest.json

3、如果这个manifest.json存在,则表明安装了这个扩展

这种方式目前一个比较大的问题的是因为要循环那个大列表,所以有点耗时。当然这样方式chrome浏览器后续可能会fixed掉。

还有一种方式就是开发一个扩展,专门用来测试用户安装了哪些插件,以及这些插件有没有植入css和JS,并且植入的CSS和JS是否对当前页面有影响。当然这种方式需要用户的配合才能进行。

如果你有其他更好的方式,欢迎一起讨论。

本文链接:http://welefen.com/post/chrome-addons-can-reduce-page-speed.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。