浏览器模型问题
多进程与多线程
浏览器的多进程
以chrome为代表的主流浏览器都是使用多进程的模型,主要有五种进程
- Browser Process: 浏览器主进程,负责主控和调用,创建和销毁其他进程。
- GPU Process: 主要负责GPU相关操作。
- Renderer Process: 每创建一个tab页就会开启一个Renderer Process 负责对应的tab页的内部网页呈现的所有,比如说页面渲染,事件执行,脚本执行。这个进程是多线程的。它就是常说的浏览器内核
- Plugin Process: 启用一个插件就会创建一个对应的进程。
浏览器的多线程
Renderer Process是浏览器为每一个tab页单独启用的进程,所以每一个Renderer Process 都会有独立的渲染引擎实例。一般来说一个tab下会有如下五个线程
- CUI线程: 这个线程负责渲染页面的html元素,它再重绘和重排的时候会执行。这个线程和 JS引擎线程互斥。
HTML渲染大致分为如下几步:
- HTML被HTML解析器解析成DOM Tree, css则被css解析器解析成CSSOM Tree。
- DOM Tree和CSSOM Tree解析完成后,被附加到一起,形成渲染树(Render Tree)。
- 节点信息计算(重排),这个过程被叫做Layout(Webkit)或者Reflow(Mozilla)。即根据渲染树计算每个节点的几何信息。
- 渲染绘制(重绘),这个过程被叫做(Painting 或者 Repaint)。即根据计算好的信息绘制整个页面。
以上4步简述浏览器的一次渲染过程,理论上,每一次的dom更改或者css几何属性更改,都会引起一次浏览器的重排/重绘过程,而如果是css的非几何属性更改,则只会引起重绘过程。所以说重排一定会引起重绘,而重绘不一定会引起重排。
- JS引擎线程(chrome的V8):JS内核,在后台等待任务,负责解析运行 JS 代码,在一个 Renderer 进程之中同时只能有一个 JS 线程。(JS的单线程性)
- 定时触发线程:setTimeout和setInterval的计时器线程,由于 JS 的单线程性,所以设计成又单独的线程计时。
- 事件触发线程:负责将浏览器和其他线程触发的符合要求的事件添加到 JS 引擎队列的末尾,等待 JS 引擎执行。
- 异步请求线程:在XMLHttpRequest在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理。
关于JS单线程的解决
为了多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
web workers
web workers的概念
Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。一旦创建, 一个worker 可以将消息发送到创建它的JavaScript代码, 通过将消息发布到该代码指定的事件处理程序(反之亦然)。
web workers的用法
使用构造函数可以创建一个worker对象,构造函数接受一个JavaScript文件的URL,这个文件就是将要在worker线程中运行的代码。值得注意的是worker将会运行在与页面window对象完全不同的全局上下文中。
在worker线程中你可以运行大部分代码,但是有一些例外:
- DOM对象
- window对象的某些属性和方法
- documen对象
- parent对象
详细的信息可以参考:Functions and classes available to Web Workers
特殊种类的web workers
shared workers:可以被不同窗口的对各脚本运行,只要这些workers处于同一个主域。详细的用法会在之后的博文介绍
service workers :般作为web应用程序、浏览器和网络(如果可用)之间的代理服务。他们旨在(除开其他方面)创建有效的离线体验,拦截网络请求,以及根据网络是否可用采取合适的行动,更新驻留在服务器上的资源。他们还将允许访问推送通知和后台同步API。
从网络安全的角度看,此woekers可以被利用成一个持久化XSS的工具。