乐趣区

关于前端:深入浅出之浏览器前端视角

1. 组成部分

1. 用户界面(User Interface)

用户界面次要包含工具栏、地址栏、后退 / 后退按钮、书签菜单、可视化页面加载进度、智能下载 解决、首选项、打印等。除了浏览器主窗口显示申请的页面之外,其余显示的局部都属于用户界面。

2. 渲染引擎(Rendering Engine)

次要用来渲染动态资源(html,css,图片等),可能精确计算页面布局,可应用“回流”,“重绘”逐渐调整页面元素的地位(例如 chrome 浏览器的 blink,老版本的 webkit)。

3.Js 引擎(JavaScript Interpreter)

以 v8 引擎为例,先读取 js 源代码,应用 parse 解析器将 JavaScript 代码转换成 AST(形象语法树),再通过 Ignition 解释器,会将 AST 转换成 ByteCode(字节码)输入。

4. 网络(Networking)

用来实现网络调用或资源下载的模块, 基于 TCP 协定,如 HTTP,Websocket。(太长,后续会细说)

6. 显示后端(Display Backend)

显示后端提供绘图和窗口原语,包含:用户界面控件汇合、字体汇合。

7. 数据长久层(Data Persistence)

治理用户数据,例如书签、cookie 和偏好设置等。(太长,后续会细说)

2. 加载资源程序及流程

首先咱们须要理解有哪些资源:

  • html
  • css
  • js
  • 字体
  • 图片
  • ajax(api 接口申请)

其次须要了解加载流程:
这里比拟重要也是比拟绕的点须要着重挑出来,就是 dom,css,js 的程序,分三大类状况探讨:

1.dom 与 css

外链款式:
两者的加载是异步进行,互不烦扰的
不过 CSS 的加载会阻塞 DOM 的渲染,因为必须等 DOM 树和 CSSOM 树合并为渲染树之后,能力进行 DOM 的渲染。(这里须要着重辨别渲染和加载的区别)
行内款式与内联款式:
行内款式是 dom 的某个节点的 style 属性,内联款式是以 style 标签包裹的模式,那么前者是节点,后者是标签,他们会被当做 dom 的一部分随着 dom 的加载而加载。

2.dom 与 js

外链 js:当加载 js 文件时,会阻塞 dom 的加载,如果加载 js 工夫过久,会导致页面显示滞后,呈现“假死”状态,如果你在 head 内外链引入 js,在 js 中操作到 dom,就会获取不到 dom 出现异常,这也是为什么咱们个别会将 js 代码写在 onload 钩子中,为什么个别将 js 引入放在文档的最初地位。(题外话:defer,async 属性能够人为管制这种状况)
内联 js:按从上到下按程序加载,读到 script 标签包裹的 js 代码,立刻执行,执行期间,阻塞 dom 加载,执行完,持续向下加载。

3.css 与 js

有一种状况分外留神,在 JS 中拜访了 CSSDOM 中某个元素的款式,那么这时候就须要期待这个款式被加载实现能力持续往下执行 JS 脚本,当然反之,这两者是互不影响的。

总结:

html>css>font> 图片 js>ajax>prefetch(预加载资源)(个别状况,也能够人为管制程序)

3. 工作原理

1. 拿到 url,DNS 服务器域名解析成 ip 地址
2. 建设 TCP 连贯,三次握手

第一次握手:客户端利用过程被动关上,并向服务器端发送申请(即:发送端发送一个带有 SYN 标记的数据包给接收端)第二次握手:服务端利用过程被动关上,若批准客户端的申请,则返回一个确认报文(即:接收端接管到数据包之后,回传一个带有 SYN/ACK 标记的数据包给发送端示意确认)第三次握手:客户端接管到确认报文后,告诉下层利用过程连贯曾经建设,并向服务器发送一个确认报文。服务器接管到客户端的申请也告诉其下层利用过程连贯已建设。(最初,发送端再回传一个带有 ACK 标记的数据包给接收端,代表“握手”’完结)

3. 申请动态资源,并按(2. 加载资源程序及流程)规定加载,dom 树与 css 规定树整合成 rendertree,layout 布局实现后,ui 后端绘制到页面上(加载和渲染是同时进行的),遇到 js 的解析,由 js 解析引擎实现(这里波及到 js 的事件循环机制以及单线程,详见上面的 js 的执行机制)。
4. 断开 http 连贯,四次挥手

第一次挥手:客户端的应用程序收回连贯开释的报文,并进行发送数据。第二次挥手:服务端接管到连贯开释的报文后,收回确认报文。此时连贯处于半封闭状态,客户端不再持续向服务端发送数据,然而服务端持续向客户端发送数据。第三次挥手:若服务端没有了要向客户端发送的数据,其利用过程会告诉服务器开释 TCP 连贯
第四次挥手:客户端接管到开释报文后,必须确认。再通过 2MSL(最长报文寿命)s 后,本次 TCP 连贯正式完结。

4. 回流和重绘以及如何防止

重绘:在渲染树中的一些元素须要更新属性,而这些属性只是影响元素的外观、格调,不影响布局。
场景:元素的显隐;元素的尺寸发生变化(包含外边距、内边距、边框大小、高度和宽度等);内容发生变化;页面首次渲染;浏览器窗口尺寸发生变化
回流:在渲染树中的一部分(或者全副)因为元素的规模尺寸、布局、显隐等扭转而须要从新构建
场景:背景色,字体色彩等不扭转构造布局的款式扭转
如何防止:
1. 应用碎片文档 documenFragment, 屡次合并一次渲染
2. 防止间接批改款式,批改类名
3. 脱离文档流
当然目前大多数浏览器都进行了本身的优化 – 渲染队列,浏览器会将所有的回流,重绘放到一个队列中,将达到肯定数量或肯定间隔时间浏览器会对队列批处理,这样的目标是屡次变一次,缩小重绘,回流的次数。

5.js 的执行机制

js 是单线程的,且自上而下解析执行的,当遇到同步工作,就放到主线程中失常按程序执行,当遇到异步工作,则放到 event table 中,并将其一对一映射为函数,当满足触发条件后, 被推入 event queue,直到主线程闲暇时, 才会去 event queue 中查看是否有可执行的异步工作, 如果有就推入主线程中,js 的执行机制也叫事件循环。
多个异步工作的执行程序如何判断:
异步工作分为宏工作和微工作
宏工作:script、setTimeout、setInterval、postMessage、MessageChannel、setImmediate(Node.js 环境)。
微工作:Promise.then、Object.observe、MutationObserver、process.nextTick(Node.js 环境)。
先执行同步代码,遇到异步宏工作则将异步宏工作放入宏工作队列中,遇到异步微工作则将异步微工作放入微工作队列中,当所有同步代码执行结束后,再将异步微工作从队列中调入主线程执行,微工作执行结束后再将异步宏工作从队列中调入主线程执行,始终循环直至所有工作执行结束。

退出移动版