一个网页被显示的前生今世(二)

cover-image

###Go to 一个网页被显示的前生今世(一)

接上文

##服务器处理请求

####前台处理
当一个请求发送至服务器的时候, 应该由一个前台程序来接收这个请求并选择直接响应静态资源(静态站)还是交给后台程序进一步处理(动态网站). 这里常用的软件有Apache(阿帕奇)/Nginx, 对于大并发的应用, nginx有天然的优势.

我们来举个栗子, Apache2的默认并发连接数是200, 而nginx是直接开到65535(linux文件系统的极限). 虽然在安全性上面阿帕奇优势明显, 不过业内各种大牛(taobao/tencent)基本上都是采用直接改造nginx来满足高并发需求的.

####后台处理
动态网站的后台程序通常能够接受刚才发送的header信息, 并对数据库(通常是SQL当然还有NoSQL)进行读取啦, 添加修改删除等等操作, 并返回适当的响应.

##响应
OK, 那么我们的服务器顺利响应了正确的信息, 高兴地发出了一个HTTP/200的信号说明 Anything goes well.

报头中的Content-Type说明了返回的MIME类型, 这里是一个html文档, 这使得浏览器清楚将该响应内容以HTML的方式进行解析.Expires头表示存在时间,它允许浏览器在这个时间之前不去检查(发请求)而是放心地读取缓存, 正确的使用Expires这可以使得服务器的鸭梨大大减轻.还有一些头的信息没有列出, 大家可以参阅高性能网站建设指南(O’REILLY).

##浏览器解析HTML
好吧, 绕了一圈又说回浏览器了. 做前端的同学都懂的, 浏览器兼容性可以说是最头疼的东西.

####HTML逐步呈现
我们知道, 在IE中, MS提供了一个进度指示器来让用户知道我们的网页正在被打开. 这里的进度指示器有一个优势就是: 它让用户知道系统没有崩溃, 而是正在努力为他或她解决问题.它不仅指出了还需要等多久, 还给用户一些可以看的图形化的东西, 以使得等待不那么枯燥无味. 而通常情况下, 在这个指示器没有跑完的时候, 大部分网页就已经显示了. 所以, 我们说其实浏览器是逐步加载网页的.

当然也有特例, 我们称之为白屏, 将样式表(CSS)放在页面底部将会阻塞内容逐步呈现, 虽然实际加载页面的时间没有增加, 但是让用户感觉缓慢的页面通常会招致反感, 用户经常会不知道发生了什么而离开!

所以无论如何前端开发者都应该遵循的一个原则就是:

1
LINK标签将样式表放在HTMLhead标签中!

####其它对象
在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签(img, css, js, 甚至flash控件, etc)。这时,浏览器会额外的发送获取请求来重新获得这些文件。而这些地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等…

####JavaScript
虽然我们的浏览器脚本不止Js一种, 但是它已经成为了各种浏览器的事实标准, 下文就用”js”来代替”浏览器脚本”这一表述.

在浏览器解析HTML的时候, 经常会碰到一个script标签, 这个时候浏览器通常会被阻塞来运行js代码, 因为js代码中有可能带有对DOM的一些操作, 如果js代码的运行跟html的解析同时进行, 会导致各种错误, 所以不管是什么js代码, 这个过程是阻塞式的.

我经常看到一些刚学js的同学在头部的代码中这样写道:

1
2
3
var ele = document.getElementById("ele");
// ...
// code here

然后跑过来问为什么代码没反应. DOM压根就没有加载完整!

随后这样写道:

1
2
3
4
5
window.onload = function(){
var ele = document.getElementById("ele");
// ...
// code here
}

我们创造js code的目的通常是执行客户端代码, 也就是说多是与用户的交互. 既然这样, 那为何不把js放在最后加载呢?

1
最佳情况: 将js代码放在文档的底部(body标签闭合之前)

当然还有一种更好的方式, async, 我们在下面讲.

##ASYNC Request(异步请求)
好了, 网页加载完成了, 是不是这个时候网页就”死了”呢? 答案是 NO!绝不!

前端的同学都听说过一个名词 AJAX. OK, 引用一句话, 在Web 2.0伟大精神的指引下,页面显示完成后客户端仍与服务器端保持着联系.

继续举栗子, 当你在百度的搜索框中输入一个关键词的时候, 是不是会跳出一个实时变化的候选热门词表, 这些内容当然是从百度的服务器中实时获取的!

我们可以简单的使用Chrome开发者工具的Network窗口来监视这些ajax请求, 如果在windows下还可以用fiddler这个工具(以前Ricter逗比介绍用的).

当然, 如果我们用异步模式来加载一些并不是立刻被需要的又很臃肿的js脚本, 整个世界将会变得很nice.

还有一点就是轮询, 它的工作方式注定了它的效率不会很高, 长连接好像是一个折衷的方法, 当被轮询时服务器没有新消息它就不理会客户端, 反之在没有超时的情况下, 新消息就会做为响应返回给客户端, 这很适合网络聊天室之类的应用, 虽然大家都用QQ了谁还会用网络聊天室呢, 也许网页游戏喜欢用这个。

最近研究Nodejs的时候发现了另外一种实时性很好的技术, websocket, 它的标准更迭貌似很快, 我用了一个叫做socket.io的库来实现它发现很好用, 不知道有没有懂的大牛来讲解一下ws的实现>.o

##Summury
本文从前端的角度简单的讲了讲自己对网络应用的模式理解, 不过我也算是个初学者, 这里难免有出错的地方欢迎客官指正哈. 也希望对那些不甚明白的同学有所帮助.

EOF.