浏览器是如何工作的?
浏览器是一个复杂的软件,其主要功能是获取并展示互联网上的信息。以下是浏览器的基本工作流程:
- 用户输入URL:用户在浏览器的地址栏中输入一个网址,也就是URL(Uniform Resource Locator,统一资源定位符)。
- DNS查询:浏览器通过DNS(Domain Name System,域名系统)查询将输入的网址转化为IP地址。DNS就像是一个电话黄页,将易于记忆的网址转化为计算机可以理解的IP地址。
- 建立TCP连接:浏览器通过TCP(Transmission Control Protocol,传输控制协议)与服务器建立连接。这个过程包括“三次握手”,以确保客户端和服务器都能发送和接收数据。
- 发送HTTP请求:浏览器通过已经建立的TCP连接发送一个HTTP请求到服务器。这个请求可能是一个GET请求,要求服务器返回某个网页的内容。
- 服务器处理请求:服务器接收到浏览器的请求后,会查找并处理这个请求。这可能涉及到运行一些服务器端脚本,查询数据库,或者只是简单地返回请求的文件。
- 返回HTTP响应:服务器处理完请求后,会返回一个HTTP响应。这个响应通常包含了请求的网页的HTML代码,也可能包含一些其他的数据,如CSS文件,JavaScript文件,或者图片等。
- 解析和渲染页面:浏览器接收到服务器的响应后,会开始解析HTML代码,并根据CSS和JavaScript来渲染页面。这个过程由浏览器的渲染引擎完成,它会把HTML,CSS,和JavaScript转化为用户可以看到的网页。
- 关闭TCP连接:当浏览器完成页面的加载和渲染后,它会关闭与服务器的TCP连接,除非服务器或者浏览器决定保持这个连接以便后续的请求。
以上就是浏览器的基本工作流程。需要注意的是,现代的浏览器都有很多优化和特性,如缓存,预加载,异步加载等,这些都可以提高网页的加载速度和用户体验。但是,这些优化和特性并不会改变浏览器的基本工作流程。
浏览器的渲染引擎是如何工作的?
浏览器的渲染引擎是负责将HTML、CSS和JavaScript代码转化为用户可以看到的可视化界面的关键组件。以下是渲染引擎的基本工作流程:
-
解析HTML:
- 渲染引擎首先解析HTML文档,将其转化为DOM(Document Object Model,文档对象模型)树。DOM树是一个节点树,它代表了文档的结构,使得开发者能够改变文档的内容和样式。
-
解析CSS:
- 与此同时,渲染引擎也会解析外部和内部的CSS样式表,并将其转化为CSSOM(CSS Object Model,CSS对象模型)。
- CSS解析器会计算出DOM中每个节点的样式信息。
-
合并DOM和CSSOM:
- 渲染引擎将DOM和CSSOM结合起来,生成一个渲染树(Render Tree)。渲染树只包含需要渲染的节点(例如,由于CSS隐藏属性而不可见的DOM元素将不会出现在渲染树中)。
-
布局:
- 一旦渲染树构建完成,渲染引擎会开始布局(Layout)过程,也就是计算每个元素的大小和位置。这个过程涉及到盒模型的应用、相对和绝对定位的计算等。
-
绘制:
- 在布局完成后,渲染引擎将遍历渲染树,并使用UI后端层将每个节点绘制到屏幕上。这个过程涉及到图形的绘制、颜色的填充、文本的渲染等。
-
合成与渲染:
- 在绘制阶段后,有些浏览器会有额外的步骤,如合成(Compositing),将多个层合并到一个屏幕上。这通常涉及到硬件加速,以提高渲染性能。
-
JavaScript的介入:
- JavaScript可以在任何时候介入这个过程,通过DOM API改变DOM树的结构,或通过CSSOM API改变样式信息,这都将导致渲染树的重新构建和布局的重新计算,最终影响到绘制过程。
-
重排(Reflow)与重绘(Repaint):
- 当DOM的变化影响到元素的几何属性(宽和高)时,浏览器需要重新计算元素的几何属性,然后再进行绘制,这个过程叫做重排。
- 当DOM的变化仅仅是影响元素的外观、风格而非几何属性时(例如改变文字颜色、背景色等),此时只需重绘即可。
现代浏览器的渲染引擎还包含很多优化技术,如异步渲染、渲染队列、请求动画帧等,以提高渲染性能和响应速度。同时,浏览器也在不断地更新和改进渲染引擎,以支持新的Web标准和提高用户体验。
JS的事件循环
- 事件循环又叫做消息循环,是浏览器渲染主线程的工作方式。
- 在Chrome的源码中,它开启一个不会结束的for循环,每次循环从消息队列中取出第一个任务执行,而其它线程只需要在合适的时候将任务加入到队列末尾即可。
- 过去把消息队列简单分为宏队列和微队列,目前已无法满足复杂的浏览器环境,取而代之的是一种更加灵活多变的处理方式。
根据W3C官方的解释,每个任务有不同的类型,不同任务可以有不同的任务队列。不同任务队列有不同的优先级,在一次事件循环中,有浏览器决定取哪一个队列的任务。但浏览器必须有一个微队列,微队列的任务必须具有最高优先级,必须优先调度执行。
例:
- 微任务 Promise.resolve().then(fn)
- 用户交互任务
- 网络任务
JS中计时器可以做到精确计时么?为什么?
- 受事件循环的影响,计时器的回调函数只能在主线程空闲时执行,因此带来误差
- 按照W3C的标准,浏览器实现计时器时,如果嵌套层级超过5层,则会带有4ms的最少时间,在计时时间少于4ms时,带来变差
操作系统的计时函数本身就有少量偏差 - 计算机硬件没有原子钟,无法做到精确计时
JS 单线程 事件循环 异步的关系
单线程是异步产生的原因
事件循环是异步的实现方式