1.浏览器渲染过程
① 首先是DOM树和CSSOM树的构建,分为解析,Token化,生成Nodes并构建几个过程
- 解析:对获得的HTML原始字节码进行解码,得到相应字符串
- Token化:根据得到的字符串,通过词法分析器进行Token化,Token会注明开始标签,结束标签,文本标签等
- 生成Nodes并构建:根据Token化标签生成相应的Nodes,并将Nodes串联起来,构建DOM树和CSSOM树
PS1:并非Token化全部完成后才会去生成Nodes,而是边Token化边生成Nodes,这样当Token化完成后DOM树和CSSOM树也就构建完成了
PS2:js标签若不设置async或defer属性,会阻塞DOM树的构建,等待js代码解析并执行完毕才会继续构建DOM树,这时若js操作了还未构建完成的DOM就会报错; js并不会阻塞CSSOM树构建,由于js可能会对CSS进行操作,因此js会等待CSSOM构建完成后才会执行,而又由于js会阻塞DOM树构建,因此等待CSSOM构建时也会阻塞DOM树构建,这就是所谓的CSS阻塞
PS3:CSSOM树要完全构建完成后才能使用,因为后面的CSS样式能会覆盖前面的CSS样式
② DOM树和CSSOM树构建完毕后,构建Render树
- Render树为每一个节点构建一个RenderObject,它的每一个节点几乎都与DOM树的结点对应,并有相应的CSS样式属性
- 一些标签和元素会被Render树忽略,如html,<script>,<link>等标签,display被设置为none的元素
- 构建Render Layer树,根据元素属性确定是否被选中分层,如是否为根元素,是否透明,是否设置z-index,是否有内容溢出等等,根据这些属性对RenderObject进行分层,未被选中的元素从属于其父节点的Render Layer
③ 布局,根据Render树计算节点的确切位置和大小进行布局
④ 渲染,根据布局进行网页绘制,完成渲染
重绘和重排
重排会触发重新计算layout过程
重绘会触发重新渲染Paint过程
重排一定重绘,但重绘不一定重排
如何减少重绘和重排
当需要进行的操作会引起多次重绘,重排时, 先将该元素设置为display: none, 然后对其进行操作, 最后再取消display: none, 这样只触发两次重排
使用CSS3实现动画, 而不是使用js操作DOM
添加元素时, 使用文档碎片Fragment创建子树, 然后拷贝到文档流中, 只触发一次重排
拷贝旧节点, 对拷贝节点进行操作, 然后用新节点替换旧节点, 只触发一次重排
大量样式发生变化时, 采用切换类名或cssText改变, 而不是每一条去改变
使用局部变量缓存布局信息, 因为每次读取布局信息都会使浏览器立即执行渲染队列中的“待处理变化”, 触发重排, 因此我们需要减少读取次数, 使用局部变量存储布局信息参与计算, 进而减少直接读取布局信息次数
2.webSocket
webSocket是一个持久性协议, 而HTTP是非持久性协议
HTTP是一个请求对应一个回应, 即使存在长连接, 也只能不停请求获取响应, 不能由服务端直接向客户端发送消息
webSocket支持双工通信, 客户端可以主动向服务端发送消息, 服务端也可以主动向客户端发送消息
webSocket是基于HTTP协议的, 或者说是借用HTTP协议完成一部分的握手, 它必须依赖 HTTP 协议进行一次握手 ,握手成功后,数据就直接从 TCP 通道传输,与 HTTP 无关了. 即webSocket分为两部分:HTTP握手+TCP传输
它比HTTP协议多携带了一些信息:
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
其中,
Upgrade: websocket和Connection: Upgrade通知服务器我要开启webSocket通信;
Sec-WebSocket-Key是一个Base64 encode的值, 是浏览器随机生成的, 需要服务端返回正确的Sec-WebSocket-Accept值才能建立连接, 否则会报错, Sec-WebSocket-Accept值是通过Sec-WebSocket-Key值进行计算的;
Sec-WebSocket-Protocol指定协议;
Sec-WebSocket-Version指定版本
服务端会返回相应的响应:
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Upgrade: websocket和Connection: Upgrade通知客户端我采用webSocket成功建立连接了;
Sec-WebSocket-Accept返回确认值, 只有Sec-WebSocket-Key字段的值经过固定算法加密后的数据和响应头里的Sec-WebSocket-Accept的值保持一致,该连接才会被认可建立;
Sec-WebSocket-Protocol最终采取的协议
在握手成功后, 将不再依赖HTTP协议, 而是转为webSocket协议, 通信时不再使用 HTTP 的数据帧,而采用 WebSocket独立的数据帧, 因此可实现客户端与服务端的双工通信.
3. Nodejs优缺点及适用场景
Nodejs主要特点:
- 异步事件驱动
- 非阻塞I/O
- 单线程(主线程)
- 性能好
异步事件驱动
主要是使用异步回调实现, 当遇到阻塞任务时, 放到事件队列, 通过主线程进行事件队列循环执行, 不让事件阻塞主线程, 在合适时机去执行这些事件
非阻塞I/O
遇到I/O操作时, 会生成一个回调函数放入事件队列中, 当同步代码执行完毕, 再去执行相应回调
单线程
利用事件驱动和异步回调实现非堵塞, 但主线程是单线程的
性能好
底层选择用c++和v8来实现的, 采用事件驱动, 异步回调, 性能很好
适用场景:
I/O密集型, 频繁I/O操作, 但对CPU使用率不高, 非堵塞I/O使用于此场景
不适用场景:
CPU密集型, 复杂计算操作, CPU占用率很高, 但I/O操作很少