浏览器面试——js加载

浏览器的主要功能是将用户选择的web资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式通常是HTML,也包括PDF、image及其他格式。用户用URI来指定所请求资源的位置,在网络一章有更多讨论。

HTML和CSS规范中规定了浏览器解释html文档的方式,由W3C组织对这些规范进行维护。


浏览器的主要构成(High Level Structure)

  1. 用户界面 - 包括地址栏、后退/前进按钮、书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分。

  2. 浏览器引擎 - 用来查询及操作渲染引擎的接口。

  3. 渲染引擎 - 用来显示请求的内容,例如,如果请求内容为html,它负责解析html及css,并将解析后的结果显示出来。

  4. 网络 - 用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作。

  5. UI后端 - 用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口。

  6. JS解释器 - 用来解释执行JS代码。

  7. 数据存储 - 属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术


渲染引擎:

渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。

Firefox、Chrome和Safari是基于两种渲染引擎构建的,Firefox使用Geoko——Mozilla自主研发的渲染引擎,Safari和Chrome都使用webkit。

 渲染引擎首先通过网络获得所请求文档的内容,下面是渲染引擎在取得内容之后的基本流程:

  解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树

Render树构建好了之后,将会执行布局过程,它将确定每个节点在屏幕上的确切坐标。

再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。

值得注意的是,这个过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的html都解析完成之后再去构建和布局render树。它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。

Webkit中元素的定位称为布局,而Gecko中称为回流。


hmtl不能被一般的自顶向下或自底向上的解析器所解析。

原因是:

  1. 这门语言本身的宽容特性

  2. 浏览器对一些常见的非法html有容错机制

  3. 解析过程是往复的,通常源码不会在解析过程中发生改变,但在html中,脚本标签包含的“document.write”可能添加标签,这说明在解析过程中实际上修改了输入。

浏览器为html定制了专属的解析器。


浏览器对js脚本的解析

script标签每次出现都会霸道的让页面等待脚本的解析和执行,同样,当使用script的src属性加载页面时,浏览器必须先花时间下载外链文件中的代码,然后解析并执行。在这个过程中,页面渲染和用户交互是完全被阻塞的。

浏览器之所以产生这样的行为,是因为当前HTML页面无从知晓JS的动作:JS可能会向document里添加内容、引入其它元素、甚至关闭标签。

所以浏览器会先(下载和)执行JS代码,然后才解析和渲染页面。


js加载优化

想要使页面得到更快的渲染,一是优化脚本的执行速度,例如使用观察者模式减少初始化代码的执行数量,这并不在这篇文章的阐述范围之内。请牢记,默认状态下,所有的脚本必须被执行后,页面才会开始渲染。即在浏览器解析页面之前,须先读取并执行脚本。我们现在试着对脚本的下载过程进行优化。

现代浏览器都允许并行下载JS文件但JS文件的下载过程仍然会阻塞其他比如图片资源的下载。尽管JS文件的下载并不会相互影响,但是浏览器会等待全部的JS代码下载完成才执行之。

1. 优化JS的首要规则:将脚本放在底部

这样做可以防止脚本代码的下载与执行阻塞页面其它资源,比如图片的下载(下载往往需要更多的时间),以尽量减少对整个页面下载的影响

如果把脚本文件放在头部,那么需要等到所有脚本下载并执行完毕后才能下载图片等其他资源,这是多么的可怕啊。但如果我们把脚本放在body标签的尾部,则可以是其它资源的下载和脚本的下载与执行并发进行,能够大大加快页面的下载速度。

2. 减少script标签的数量,减少延时

3. 不要把内嵌脚本紧跟在link标签后面

这样做会导致页面阻塞去等待样式表的下载,因为需要确保内嵌脚本在执行时能获得最准确的样式信息。

4. 减少外链脚本文件的数量——将多个外链JS文件合并成一个以减少HTTP开销


无阻塞的脚本

无阻塞脚本意味着脚本的下载和执行不阻塞其他资源的下载和页面的解析。

可以通过设置script标签的defer和async属性使其拥有不阻塞的特性,它们仅对外部链接的script有效。 

带有async或者defer的script都会立刻下载并不阻塞页面解析,它们的不同之处在于script执行的时机。

(1)defer:

1、如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script;

2、defer 与 DOMContentLoaded

如果 script 标签中包含 defer,那么这一块脚本将不会影响 HTML 文档的解析,而是等到 HTML 解析完成后才会执行。而 DOMContentLoaded 只有在 defer 脚本执行结束后才会被触发。 所以这意味着什么呢?HTML 文档解析不受影响,等 DOM 构建完成之后 defer 脚本执行,但脚本执行之前需要等待 CSSOM 构建完成。在 DOM、CSSOM 构建完毕,defer 脚本执行完成之后,DOMContentLoaded 事件触发。

contextload改为DOMContentLoad

(2)async:

1、async的执行,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行。

2、async 与 DOMContentLoaded

如果 script 标签中包含 async,则 HTML 文档构建不受影响,解析完毕后,DOMContentLoaded 触发,而不需要等待 async 脚本执行、样式表加载等等。

(3)defer和async的区别:

(1)defer 和 async 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)

(2)它俩的差别在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的

(3)关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用

(4)async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行

仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics


注意:带有defer属性的脚本执行也不一定按照顺序执行,有风险!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • JavaScript代码嵌入网页的方法 JavaScript代码只有嵌入网页,才能在用户浏览网页时运行。 网页中嵌...
    许先生__阅读 1,148评论 0 1
  • JavaScript脚本对现代网站来说是必不可少的。当用户访问站点,需要下载各种资源,例如JS脚本,CSS,图片,...
    张歆琳阅读 9,053评论 0 24
  • 简单介绍JavaScript的发展历史 JavaScript因互联网而生,回顾它的历史要从浏览器的历史讲起。 19...
    _Dot912阅读 480评论 0 3
  • 本文总结一下浏览器在 javascript 的加载方式。关键词:异步加载(async loading),延迟加载(...
    4ea0af17fd67阅读 1,057评论 0 2
  • 前端必读:浏览器内部工作原理[https://kb.cnblogs.com/page/129756/] 作者: T...
    我是强强阅读 1,138评论 0 2