WebQQ 2.0实现分析(一)

WebQQ

Web前端开发听上去并不是一份牛逼的工作,但如果你的Web前端开发搞的很牛逼,那么你一定是做到了Steve Souders提到的那14条,个人认为如果前端开发有什么所谓的金科玉律,应该就是指他们了。Yahoo!后来还据此专门为Firebug开发了一个插件:YSlow

闭门造车不是个好主意,Web QQ 2.0的前端我认为做的很有创意,所以我准备停下来,认真分析一下其实现。在开始分析之前,先来了解一些基础知识。

基础知识

那些不得不说的工具

Firebug

“工欲善其事,必先利其器”,我所使用的分析工具简单而强大,上文已经提到过:Firebug + YSlow,显然,你还需要一个FireFox(推荐使用FX 3.6,4.0的组件比较少吧?)。

一次页面访问的执行顺序是怎样的?

当用户通过浏览器访问指定页面(url)时,浏览器将其包装为一个http请求,该请求除包含待访问页面地址及若干参数(可选)外,还包含了用户的浏览器及操作系统信息,语言、编码信息,缓存信息及其它一些浏览器配置信息等。

这是请求http://web2.qq.com/时的头信息(部分):

1
2
3
4
5
6
7
8
9
10
GET / HTTP/1.1
Host: web2.qq.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.2.10) Gecko/20100915 Ubuntu/10.04 (lucid) Firefox/3.6.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
If-Modified-Since: Wed, 29 Sep 2010 10:50:21 GMT

这是对上述请求的响应的头信息:

1
2
3
4
5
6
7
HTTP/1.1 304 Not Modified
Server: nginx
Date: Thu, 30 Sep 2010 03:18:22 GMT
Last-Modified: Wed, 29 Sep 2010 10:50:21 GMT
Connection: close
Expires: Thu, 07 Oct 2010 03:18:22 GMT
Cache-Control: max-age=604800

具体的响应内容,就是我们能够看到的页面了。但由于一次页面访问可能导致多次发送http请求(事实上,由于图片、脚本、样式表的存在,这几乎是必然的),页面上的内容并不会一次全部加载完成,而是陆续加载。

关于http请求的更多内容见这里

一次http请求的执行顺序是怎样的?

从浏览器发出http请求,到收到服务器响应,整个过程通常可能持续几毫秒到几秒不等的时间,其顺序如下:

  1. 域名解析:时间一般比较短(n ms),取决于所访问站点隶属的DNS服务器及网络环境。
  2. 建立连接:时间一般稍长(n*10^1 ms),取决于所访问站点对应服务器及网络环境。
  3. 发送请求:时间一般很短(接近于0 ms),取决于本地浏览器。
  4. 等待响应:时间一般稍长(n*10^1 – n*10^3 ms),取决于所访问站点对应服务器的处理效率及网络环境。
  5. 接收数据:时间一般稍长(n*10^1 – n*10^3 ms),取决于请求内容的多少及网络环境。

下面将根据http请求发送顺序具体分析webqq 2.0的http请求。

http请求分析

分析之前,先看一张图,这是http请求序列中的一小部分(由于Web QQ 2.0资源更新比较频繁,内容不尽相同,但影响不大)。后面还会有更加详细的分解:

Web QQ 2.0资源加载序列(局部)

我们注意到图中有颜色为蓝色和红色的两条竖线,蓝色线表示页面的所有DOM(文档对象模型)加载完成,为DomContentLoaded事件的触发点,jQuery$(document).ready()将开始执行,IE不支持该事件;红色线为文档load事件的触发点,意味着所有内容加载完毕(含图片资源等),window.onload()将会被执行。

1. 加载页面

首先看一下具体响应页面内容(这也是上图中的第一个http请求)。为了方便,我直接将分析内容以注释形式夹在其中(位于对应内容上方):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!-- 这是html5的文档标识,web qq 2.0明显已经为html5的到来做好了准备 -->
<!DOCTYPE HTML>
< html >
< head >
     < meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" />
     <!-- 针对IE8,使用IE7进行渲染 -->
     < meta http-equiv = "X-UA-Compatible" content = "IE=7" />
     < meta name = "keywords" content = "QQ、QQ网页桌面、WebQQ 2.0、web QQ、网页聊天、网页QQ、QQ被封、QQ空间、腾讯微博、QQ邮箱、腾讯新闻、QQlive、QQ地图、QQ校友、QQ团购" />
     < meta name = "description" content = "WebQQ2.0以个人化门户为理念,致力于满足用户聊QQ,看资讯、写微博、玩游戏、听音乐、拼团购、收发邮件及网络存储等各种网络生活需求,打造一站式个人网络生活平台。" />
     < meta name = "copyright" content = "腾讯公司" />
     <!-- 主要是针对移动终端等,禁止用户缩放 -->
     < meta name = "viewport" content = "minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0, width=device-width, user-scalable=no" >
     < title >WebQQ 2.0</ title >
     <!-- 设置各种环境下的图标 -->
     < link rel = "icon" href = "/favicon.ico" type = "image/x-icon" />
     < link rel = "shortcut icon" href = "/favicon.ico" type = "image/x-icon" />
     < link rel = "bookmark" href = "/favicon.ico" type = "image/x-icon" />
     < link rel = "apple-touch-icon" href = "/webqq.png" />
     <!-- 加载jet库 -->
     < script type = "text/javascript" src = "./js/jet.all.js?t=20101014002" ></ script >
     <!-- 加载样式表 -->
     < link type = "text/css" rel = "stylesheet" href = "http://hp.qq.com/webqqpic/style/jet.all.css?t=20101014002" />
     < link type = "text/css" rel = "stylesheet" href = "http://hp.qq.com/webqqpic/style/qqweb.main.css?t=20101014002" />
     < link id = "qqwebSkin" type = "text/css" rel = "stylesheet" href = "about:blank" />
     < script type = "text/javascript" >
         Jet().$package(function(J){
             // 加载主题样式
             var themeId = "theme_wood1";
             J.out("themeId:  "+themeId)
             J.http.loadCss("http://hp.qq.com/webqqpic/style/" + themeId + "/qqweb.theme.css?t=20101014002",{node:J.dom.id("qqwebSkin")});
         });
     </ script >
</ head >
< body >
     <!-- 需要开启JavaScript -->
     < noscript >
         < div class = "noscript" >
             你好,需要浏览器开启JavaScript功能来帮助你使用WebQQ2.0。< br />
             请设置浏览器开启 JavaScript功能,然后重试。
         </ div >
     </ noscript >
     <!-- 针对ios触屏用户,添加触屏响应 -->
     < iframe id = "touchpad" src = "./touchpad.html" ></ iframe >
     < div id = "desktop" class = "EQQ_Container" >
         < div id = "topBar" >
             < div class = "topBar_bg" >
                 < a title = "20101014002" id = "logo" href = "http://im.qq.com/webqq" target = "_blank" ></ a >
                 < div id = "qqBar" class = "qqBar" >
                 </ div >
             </ div >
         </ div >
         < div id = "mainPanel" >
             < div id = "sideBarReplacement" class = "sideBarReplacement" >
             </ div >
             < div id = "toggleBar" class = "toggleBar toggleBar_show" title = "打开侧边栏" ></ div >
         </ div >
         < div id = "toolBar" >
             < div class = "toolBar_bg" >
                 < div id = "statusBar" >
                     < div id = "settingCenterButton" class = "settingCenterButton" ></ div >
                 </ div >
                 < div id = "taskBar" ></ div >
             </ div >
         </ div >
     </ div >
     < script type = "text/javascript" src = "http://pingjs.qq.com/tcss.ping.js" ></ script >
     < script type = 'text/javascript' >
         Jet().$package(function(J){
             if(J.platform.iPad) document.querySelector('#touchpad').style.display = 'block';
         });
         if(typeof(pgvMain) == 'function'){
             // 与页面访问及缓存控制相关,腾讯平台共用的一个统计功能,暂且放下
             pgvMain();
         }
     </ script >
     < script type = "text/javascript" src = "./js/qqweb.all.js?t=20101014002" ></ script >
</ body >
</ html >

如果在没有缓存的情况下,下载该页面(大约1.4K)可能耗费n ms的时间,资源的加载时间与其大小成正比(同时受当时网络环境影响)。

通过Firebug查看该页面效果是这样的:

初始响应内容

2. 加载资源

正如我们在前面的序列图中看到的,浏览器在处理返回的页面过程(从上到下顺序执行,遇到错误将中止)中,该页面所使用(直接使用)的脚本及样式表会依次加载。加载过程是异步的,后续资源不需要等待前面的资源加载完成,但如果遇到内联或外联脚本,则需等待脚本执行后才能继续。因此,如果可能,将脚本置于页面底部是明智的选择:

  • Line 20: http://web2.qq.com/js/jet.all.js?t=20101014002
  • Line 22: http://hp.qq.com/webqqpic/style/jet.all.css?t=20101014002
  • Line 23: http://hp.qq.com/webqqpic/style/qqweb.main.css?t=20101014002
  • Line 66: http://pingjs.qq.com/tcss.ping.js
  • Line 78: http://web2.qq.com/js/qqweb.all.js?t=20101014002
3. 执行页面

接下来便是执行脚本以及加载各DOM所需的资源并完成元素绘制。

  • Line 25:内联脚本功能为加载当前使用的主题样式,并将所加载的样式表嵌入到Line 24对应的结点中。
  • Line 43:针对触屏用户添加触屏响应,将其置入一个iframe中。
  • Line 47:样式填充——加载logo(背景图片元素,由qqweb.main.css给出)。
  • Line 75:内联脚本功能为处理缓存(cookie)并发送统计信息。

通过上面的http请求顺序,我们也能够看出:页面执行是从上到下的,DOM元素(如Line 47的logo)必须等到前面的脚本(Line 25)执行完毕才能开始绘制,这也印证了我们上文提到的尽量将脚本放在页面底部的必要性。当然,如果脚本本身不需要立即执行(如这里的jet库),放在页面顶部反而是必须的,后续脚本的执行依赖它们,需要等待其加载完成才能继续执行,前面序列图的时间线已经很好的证明了这一点。

Web QQ的实现逻辑全部位于上文分析的页面底部的javascript文件qqweb.all.js中,其实现基于JET

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值