我们每天上网,用的最多的应用软件之一是浏览器,我们用浏览器看新闻,看视频,基本上,只要是现在上网,大部分人都是使用浏览器。浏览器也有很多,但是,总体上分为四个半流派,第一个是微软公司出的Intenet Explore, 这个占有率很高,尤其是中国的市场上;第二个流派是谷歌公司出的Chome浏览器;第三个流派是Mozilla公司出的Firefox流派;第四个流派是苹果公司出的Safari;第五个流派是Opera基本上就是这些吧。
有同学可能问,我从来不用上面这些浏览器,我用的是360浏览器,QQ浏览器或者各种百度全家桶浏览器,其实,这些有中国特色的自主研发的软件,都是基于以上我说的那些浏览器来改版的。比如说加了一个外壳,让浏览器可以记录密码,同步书签等功能。我这次节目不做浏览器的测评,不评价哪个浏览器好用,主要是讲浏览器的一个工作原理。以前我做过一期,名字叫钻钻牛角尖,电脑开机开了啥。那一期是研究电脑开机的,结果,有人告诉我没必要这么复杂,装个360软件,就能加速电脑开机。而且我还和那个朋友争吵了一下,最后不欢而散吧。我这一期节目,没啥用处,即使研究浏览器的原理,也不会让上网速度变快。这只是一个程序员的怪癖,我就是喜欢研究这种东西。以后我还会讲各种音频格式之间的差别,各种图片格式之间的差别,各种视频格式之间的差别,还有各种自拍加的滤镜的工作原理等等,怎么说的,研究这个并没有卵用,只是我自己的业余爱好,希望不喜欢听的同学不要去留言说,你研究这个有啥用了,我也知道,真的没啥用。因为我上一次做电脑开机的那个音频,非得有人去问研究这个能让电脑变快么?如果不能,还不如装个360一键加速呢…
在这个节目里,主要讲两个浏览器,一个是Firefox,一个是chrome和safari和Opera。至于为什么把chrome和safari还有Opera放在一起讲呢?那是因为这三个浏览器用的是相同的排版引擎,是苹果的WebKit,是开源的。其实这个项目最初也不是苹果原创的,而是苹果基于另一个开源项目,那个开源项目是KDE的HTML排版引擎,名字叫KHTML,还有一个KDE的另一个Javascript引擎,名字叫KJS。苹果公司开始的时候是基于这两个开源项目,做出了自己的项目,名字分别是WebCore,这个对应于KDE的KHTML,另一个项目叫JavascriptCore,这个对应于KDE的KJS这个项目。这个两个项目的目的是可以移植到OS X系统上,毕竟人家苹果是商业公司,而且苹果做的事情非常的合乎法律,给KDE的KHTML和KJS也作出了不少的技术改进,然后KDE的这两个项目,也获益匪浅吧,起码开始的时候是这样。
如果用过苹果电脑的同学,尤其是早期的苹果电脑,苹果电脑上是没有一个特别靠谱的浏览器,这东西可能是不太容易做。苹果电脑上一度装微软出的InternetExplore 5浏览器,其实微软和苹果之间,有说不清道不明的爱慕关系,经常互相帮助,相爱相杀。苹果公司就基于这两个东西,然后就推出了自己的浏览器,也就是safari浏览器,,2003年发布的,safari浏览器。这个浏览器我用过,因为那时候我正在读本科,要去做实验,学校的实验室里新买了一批设备,这批设备需要处理数据的就是一台iMac,当年是新款的,那也是我第一次使用苹果电脑。刚开始感觉并不好用。现在记忆最深刻的就是这台苹果电脑,还有一台离心机,非常大的离心机,可能得有直径1米多,然后我有个同学突发奇想,把刚洗过的衬衫塞进去,想看看能不能把衣服甩干,然后甩了10来分钟,衬衫甩成了破布,已经不能穿了。实验室去了好几年,结果,就记住了这两件事情,一台苹果电脑,一个离心机,其它的都忘记了。
继续来说苹果,然后苹果对webkit的改进越来越多,和开源社区也就越走越远,再后来,就彻底分手了。这个分手只是和KHTML那个项目分手了,具体的分手过程,我记得KDE的一个开发者曾经写过一个文章,来吐槽这件事情,当年在开源届也算引起过不大不小的轰动,甚至让Apple公司吓得赶紧联系KHTML的开发者,看看还能不能复婚,别那么快离婚。后来KHTML这个项目确实又从Apple中接受了不少新的特性,来改进KHTML的渲染速度。但是,我猜测的一个原因,Apple是商业公司,KDE是开源组织,商业组织是向钱看,我说的向钱看是金钱的钱,开源组织是不太注重金钱驱动的,结果呢,这些开源的项目因为不赚钱,大家紧张了一阵子,又开始跟不上苹果的节奏了,因为商业公司的项目推进能力,远远高于开源组织,结果,最后还是闹分手了。其实,开源组织有时候吧,赚不到钱,只能兼职做做,很多时候项目的质量并没有商业公司高,在后来,Apple的webkit在很多方面全面超越了KHTML。当然,KDE也知道这件事儿,从KDE4.5开始,KDE就已经使用苹果的webkit这个开源组件,当然了,开源的那个KHTML还是继续开发,也继续用在KDE上吗。
苹果也在继续开发webkit,开发的成果也继续开源。可能有很多人觉得,苹果太尼玛封闭了,其实不是的,苹果是个商业公司,他肯定首先考虑的是商业利益,如果开源能获得巨大的商业利益,他肯定开源,所以,苹果开源了几个大杀器,黑科技。其中我知道的几个有前面我说的这个webki,还有一个大杀器是llvm,这个项目也极其重要,既然说到这里了,我就稍微的说一下,llvm呢,是一个开源的编译器项目,是C++写的。以前,包括现在,最重要的开源的编译器是gcc,就是理查德斯托曼做的那个gcc项目,曾经,gcc是开源届的核心地位,现在也差不多,因为几乎所有的开源软件,都需要使用gcc来编译成二进制代码,然后,这个组织脾气不太好,基本上处于那个地位,可能总是有缺点吧,而且处于核心地位,缺点也容易被放大,gcc可以说是在所有开源项目中,受到的批评最多的一个,比linux都多。但是,即使收到批评,你还不得不用它,苹果就是这样,给gcc捐献了大笔的钞票,没啥效果,因为有求于gcc的,可不止苹果一家。然后,苹果公司就搞了一个LLVM项目,来代替gcc在开源中的地位,LLVM是一个简称,全称是Low Level Vitual Machine,全称没啥人知道,我也是google一下,才敢写在这里。然后,LLVM太重要了,还获得了ACM颁发的一个大奖,来奖励Apple开源的这个LLVM项目。然后Apple率先垂范,把Gcc从默认编译器的位置拉了下来。因为Gcc这个项目组,和其它大的开源项目组,之间的龌龊事情也不少,比如FreeBSD项目也是早就看Gcc不爽了,但是,苦于自己没有编译器,只能忍气吞声,结果LLVM一出来,FreeBSD马上就把GCC给集成进来的,然后,一个以前看起来非常狂妄自大的计划被FreeBSD提上了日程,不光gcc,而是要把所有GNU组件都替换出来,然后就有了lldb, libc,compiler-rt这一系列项目,个人觉得,以FreeBSD社区那种比较高贵的气质,完全替换掉GNU项目,是有很大可能的。这一切,都是Apple花了5年时间,搞出来了一个LLVM,然后把这个编译器项目开源的原因。
llvm的logo是我最喜欢的logo
稍微跑了一下题,拐到编译器上了,再强行拐回来,继续说Apple这个webkit。苹果继续改进webkit,然后webkit也就越来越好用,速度越来越快,然后呢,另一家公司叫Google,也打算做个浏览器,二话不说,直接把苹果开源的这个引擎webkit拿过来就用,这是合乎法律的,因为开源么。然后一贯嘴上说不作恶的google公司实际上恶心事儿也干过不少的google和一贯表面非常高冷但是私底下对政府部门低三下四的apple公司又杠上了。chrome继承了apple公司的webkit,然后加以改进,把认为不行的代码丢了,尤其是javascript的部分,用了自己引以为豪的v8引擎,这个v8引擎的横空出世,让很多人也是惊讶的不行,然后javascript开始从前端到后段,差点儿通吃。让不少程序员惊呼,我操,js这是要上天么?然后,后来发现这种担心是多余的,因为前段进入了百花齐放的时代,每年都会出现至少365个javascript写的库,每天一个吧,然后循环往复,至今已经持续了好几年了。这个话题太容易引起争端,那个前端库更好呢?这个得看情况,因为一旦争论结束,又会出现更多新的js库,没办法,程序员就是这么搞笑,还是老老实实的用php这个世界上最好的语言靠谱。
然后google的chrome是世界上占有率第一的浏览器,由于在中国某种神秘的力量,chrome的占有率很可能是倒数第一,如果你看到有人用chrome,很可能他就是个程序员。接下来,还有一个更小众的浏览器,他的名字叫Opera,据说已经被中国的360公司收购了,这家公司浏览器的引擎,也是webkit。因此,chrome/safari/opera,这三个浏览器,在渲染方面,大同小异,来自一个妈。
另外一个分支就是大名鼎鼎的火狐浏览器,Firefox,这个在国内可能用的人也不多,如果你看到有人用firefox,可能,也是个程序员,如果你看到桌面上有三四个浏览器,并且同时使用,那100%是个前端程序员,尤其是你看到有人还在测试Internet Explorer 6这个浏览器,那100%是个给中国国企开发软件的前端程序员,中国国企和IE6这个浏览器,已经水乳交融,今生今世都不再分离了,即使这个浏览器已经15岁了,15岁,在IT行业,和永远一样远。但是,大型国企爱IE6,比如说,在2016年,我看到过某大型钢铁企业,赫然写着网站要支持IE6,真是让我百思不得其解的一件事情。火狐浏览器用的引擎的名字叫Gecko, 这个软件,曾经一度讨论要不要也把引擎换成webkit,最后,还是继续用这个Gecko,在英语中是壁虎的意思。好了,背景就介绍到这里,微软的不考虑了,他有自己独特的渲染引擎,但是,可以研究他家引擎源代码的,就是微软的人,网上可以找到的材料并不多。这里只讲这两个引擎,一个是webkit,用这个引擎的有三个浏览器,chrome,safari和opera;还有一个是Gecko,用这个引擎的是Firefox。·
这些浏览器虽然各不相同,但是作用是类似的,就是能把你要求的东西显示出来,并且,不同的浏览器,显示的样子大同小异,稍微的有一些不同。因为不同的厂商出品的浏览器,是有一些细微的不同。之所以能显示的大同小异,是因为,这些厂商都要遵守一个协议,这些标准就是HTML和CSS,这些标准由一个公益组织来管理,这个公益组织的名字叫W3C,中文名叫万维网联盟来维护。我们上网的过程,就是把HTML和CSS的内容从网站上下载下来,然后将这些内容解析以后,显示在屏幕上。这个过程,需要用到的核心技术就是我上面所提到的两个引擎,webkit和Gecko的工作。负责显示请求的内容,把网站上下载下来的HTML和CSS,解析以后,展现出来。我对这个过程非常的好奇,好多年前,我就对浏览器是如何工作的非常的好奇,然后就研究了一下,自以为可以把自己给糊弄过去了,因此,我就说一下那两个引擎的工作原理。
主要的流程是这样的,显示引擎会从网络层请求需要显示的文档,然后引擎开始工作。因为所有的网页都是HTML和CSS文档,引擎开始解析这个HTML文档,将整个文档解析成两棵树,一棵树叫内容树,这棵树上的节点是HTML的标记。还有一棵树叫呈现树,这棵树势解析样式元素,呈现树是节点的样式,比如字体的大小,颜色等等。呈现树主要是带有视觉属性比如颜色啊,尺寸啊,背景等等的一些矩形,这些矩形呢,就按照一定的顺序显示在屏幕上。当这个视觉效果显示出来以后,也就是一些矩形。再进入下一个阶段,就是将内容树的节点,计算一个坐标,每个节点都有一个独一无二的位置。有了这两个信息,再然后就是根据这两个信息,把内容绘制到屏幕上,引擎会遍历整棵树,然后将树上的每个节点,都画在屏幕上。
web browser architecture
为了能有更好的用户体验,引擎肯定是将内容以最快的速度画到屏幕上,而不是等所有的内容都下载完毕,才开始绘图,那样是非常影响用户体验的。所以,我们经常会碰到这种情况,某个地方的图片还没有显示出来,只显示一个空白,文字比图片更快的显示出来。这是一种特征,不是bug。引擎不是等所有的HTML文档都解析完毕以后,才开始绘制,如果那样,碰到一个网速很慢的,网页很大的,黄花菜都凉了,那样会非常的影响用户体验。正确的展示流程是,有多少显示多少,只要有内容过来,就赶紧的先给用户看一点,不必等所有内容都下载完成。
那是不是webkit和Gecko是一样的呢?当然不是一样的,如果是一样的,那何必还要两个引擎呢?但是这两个引擎所采用的方法肯定不会有质的差别,如果有质的差别,两个都是开源的项目,那开发人员早就抄袭了,显然,这两个引擎所采用的方法大同小异。接下来呢,我要具体的描述这两个引擎所采用的方法。
在讲技术之前,先得讲一个网页的技术,叫DOM,这个做前端的程序员肯定都是知道的,Web就是基于DOM的,比如说现在前端用的最多的一个javascript库叫jQuery,这个库本质上就是一个操作DOM的工具,这个库现在是越来越大,1.8的时候,原始大小200多K,优化以后也得100来k,其实这样挺大的,尤其是考虑到大部分人用jQuery就是实现了1-2个效果,结果让自己的网页增加了100多K,想想我这个不是前端的程序员,就很不爽,当然也有解决方案,比如zepto.js就是解决这个问题的,只增加了20多k。那唠叨了这么多,到底什么是DOM呢?这是一个英文的缩写,全称是Document Object Model。我们可以把DOM看作是节点,每个节点就是一个HTML的标签,那如何解析成树呢?
这就是一个编译原理的问题了。还记得前面我讲苹果开源的那个LLVM么?那就是编译器,因为我试图把这个问题讲清楚,起码能加深我自己的印象,这次的时间又到了,下次,我要讲如何把HTML文档解析成一棵树,期间会用到编译器的知识,就是解析器和词法分析器。好了,下次再见。如果你喜欢我讲的这种钻牛角尖的内容,欢迎关注我的微信公众号——软件那些事儿——我这个公众号不扰民,每周推送一次,每次的观看量大概是300次左右。