Chrome 运行原理
浏览器地址输入 URL 后发生了什么?
地址输入之后,会经过以下流程:输入处理、开始导航、读取响应、寻找渲染进程(通过 IPC 方式与渲染进程交互)。
在浏览器中,不同的页面(或者说标签页)通常都是运行在独立的进程中的,这些进程之间需要进行进程间通信(IPC)来实现一些功能。主要的浏览器 IPC 通信方式包括:
- 消息通信(Message Communication):在浏览器中,通过 postMessage() 方法可以在不同的页面或者 iframe 之间进行消息通信。每个窗口都有自己的 window.postMessage() 方法,可以向其他窗口发送消息,也可以接收其他窗口发送过来的消息。
- websocket:websocket 是一种全双工通信协议,可以在客户端和服务器之间进行进行双向数据传输。在浏览器中,可以使用 WebSocket 对象进行 WebSocket 的创建和管理,从而在不同页面之间进行通信。
- WebRTC:WebRTC 是一个实时通信协议,它支持点对点(P2P)的音视频通讯以及文件传输等功能。如果需要在不同的页面之间进行音视频传输或文件传输,可以使用 WebRTC 技术进行实现。
需要注意的是,在浏览器中进行 IPC 通信需要考虑到安全性和隐私性。例如,在使用 postMessage() 进行消息通信时,需要防范跨域脚本攻击,保证消息的安全性和正确性;在使用 WebRTC 进行音视频通讯时,需要保证用户的隐私不被泄露。
输入处理
- 用户 URL 框输入内容后,UI 线程会判断输入都是一个 URL 地址还是一个 query 查询条件。
- 如果是 URL,直接请求站点资源。
- 如果是 query,将输入发送给搜索引擎。
开始导航
- 当用户按下回车,UI 线程通知网络线程发起一个网络请求,来获取站点内容。
- 请求过程中,
tab处于loading状态。
读取响应
- 网络线程接受到 HTTP 响应后,先检查响应头的媒体类型(
MIME Type) - 如果响应主体是一个 HTML 文件,浏览器将内容交给渲染进程处理。
- 如果拿到的是其他类型文件,比如
Zip、exe等,则交给下载管理器处理。
寻找渲染进程
- 网络线程做完所有检查后,会告知主进程数据已准备完毕,主进程确认后为这个站点寻找一个渲染进程。
- 主进程通过 IPC 消息告知渲染进程去处理本次导航。
- 渲染进程开始接收数据并告知主进程自己已开始处理,导航结束,进入文档加载阶段。
渲染进程
资源加载
- 收到主进程的消息后,开始加载 HTML 文档。
- 除此之外,还需要加载子资源,比如一些图片,CSS 样式文件以及 JS 脚本。
构建渲染树
- 构建 DOM 树,将 HTML 文本转化成浏览器能够理解的结构。
- 构建 CSSOM 树,浏览器同样不认识 CSS,需要将 CSS 代码转化为可理解的 CSSOM。
- 构建渲染树,渲染树是 DOM 树和 CSSOM 树的结合。
页面布局
- 根据渲染树计算每个结点的位置和大小。
- 在浏览器页面区域绘制元素边框。
- 遍历渲染树,将元素以盒模型的形式写入文档流。
页面绘制
-
构建图层:为特定的节点生成专用图层。
-
绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程。
-
合成线程接收指令生成图块。
-
栅格线程将图块进行栅格化。
栅格线程将图块进行栅格化,是为了将大图片拆分成多个小的图块,并且对这些小图块进行处理,从而提高图片在网页加载过程中的响应速度和用户体验。
一张大图片如果直接加载到网页上,会让页面的加载变得非常缓慢,特别是当网络速度不够快时。而将大图片拆分成多个小的图块,就可以把这些小的部分分开加载,而不是等待整张图片全部加载完成后再显示出来。
具体来说,在栅格线程将图块进行栅格化后,可以对每个小的图块进行处理,例如压缩、裁剪、缩放等操作,还可以针对图块进行缓存或者延迟加载等策略,以提升用户的访问速度和流畅度。
通过拆分图片和对图片进行处理,栅格线程可以优化图片的加载和渲染,提升网页的性能和用户的使用体验。
-
展示在屏幕上。
前端性能 performance
- 时间都花在哪
- 什么情况下卡顿
首屏优化
首屏优化是指通过一系列技术手段,尽可能地优化页面在用户访问时展示的效果,提高页面的加载速度和用户体验。常用的优化方式有以下几种。
- 压缩、分包、删除无用代码:对于 HTML、CSS、JavaScript 等资源文件,可以通过压缩、分包、删除无用代码等方式来减少它们的体积,从而减少页面的加载时间。使用一些工具,比如 Webpack,Gulp 等工具可以很方便地进行这些操作。
- 静态资源分离:将静态资源(如图片、CSS、JavaScript 等)与 HTML 文件分离,并将它们部署到不同的服务器上,以减轻服务器的负担并提高资源加载速度。
- JS 脚本非阻塞加载:使用异步加载方式加载 JavaScript 文件,避免 JavaScript 脚本的加载和执行阻塞页面的渲染。可以使用 defer 属性或者动态创建 script 标签等方式来实现。
- 缓存策略:利用浏览器的缓存机制来避免重复的请求和获取,减少网络传输时间,提高页面加载速度。可以设置 expires 和 cache-control 两种响应头来定义缓存时间,也可以使用 ETag 或者 last-modified 等机制来验证缓存的有效性。
- SSR:服务端渲染(Server-Side Rendering)可以在服务器端将页面 HTML 模板渲染成最终的 HTML 页面,然后再将其发送到客户端。这样可以减少客户端渲染所需要的时间,提高首屏加载速度和 SEO 效果。
- 预置 loading、骨架屏:在页面加载过程中,通过预置 loading 和骨架屏等方式,给用户一个良好的反馈,告诉用户内容正在加载中,避免出现长时间的空白页面或者等待状况,提高用户体验。
渲染优化
渲染优化是指通过一些技术手段,优化页面的渲染流程,提高页面的性能和用户体验。以下是几种常用的渲染优化方式。
- GPU 加速:在进行复杂的动画、过渡效果等操作时,可以利用 GPU 进行加速,提高渲染速度和帧数,从而提高用户体验。利用 CSS3 或者 Canvas 等技术,可以很方便地实现 GPU 加速。
- 减少回流、重绘:当页面元素位置、大小等属性发生变化时,浏览器会进行回流(重新计算元素布局)和重绘(重新绘制元素样式),这些操作会耗费大量的计算资源,影响页面渲染性能。因此,尽可能地减少回流和重绘操作,可以有效地提高页面性能。可以使用一些工具,如 Chrome 浏览器的 Performance、Paint 和 Layout 面板等来分析和调试页面的回流和重绘情况,找到优化的方向。
- 离屏渲染:将不需要频繁更新的元素渲染到离屏的画布上,避免其参与到主屏幕的渲染,从而提高页面的渲染速度。可以使用 CSS 的 transform 和 opacity 属性来触发元素的离屏渲染。
- 懒加载:在页面中,只有当用户滚动到某个位置时,才加载该位置下的图片或其他资源。这种方式可以减少页面一开始的加载时间和流量,提高首屏速度,同时支持按需加载,降低服务端压力。可以使用 JavaScript 插件,如 LazyLoad.js、Echo.js 等插件来实现懒加载效果。
JS 优化
JS 优化是指通过一些技术手段,优化 JavaScript 代码的性能,提高页面的响应速度和用户体验。以下几种 JS 优化方式。
- 防止内存泄露:在开发复杂的 JavaScript 应用程序时,容易出现内存泄漏的情况,导致内存占用越来越高,最终影响整个应用程序的性能。因此,需要特别注意防止内存泄漏的问题,避免不必要的资源浪费。可以使用浏览器自带的开发者工具进行内存分析,找到可能存在的内存泄漏问题。
- 循环尽早 break:在进行循环操作时,如果已经达到预期的结果,可以提前结束循环,避免浪费不必要的计算资源。比如,在数组中查找特定元素时,如果找到了目标元素,就可以使用 break 关键字提前结束循环,从而提高代码效率。
- 合理使用闭包:使用闭包可以有效地保护变量作用域,避免全局变量污染和命名冲突等问题。但是,如果过度使用闭包,会导致内存占用过大,从而影响 JavaScript 的性能。因此,需要合理使用闭包,避免出现滥用的情况。
- 减少 DOM 访问:在 JavaScript 中,访问 DOM 是一项非常耗时的操作,应该尽可能地减少对 DOM 的访问,以提高页面的响应速度和性能。可以使用缓存、批量操作、事件委托等方式来减少 DOM 访问次数。
- 防抖、节流:防抖和节流是两种优化 JavaScript 性能的方法。防抖是指在某个时间段内,只有最后一次操作会被执行,而其它操作都会被忽略。节流是指在一定时间间隔内,只执行一次操作,避免重复操作。这两种方法可以有效地降低浏览器的计算压力和网络资源消耗,提高性能和用户体验。
- Web Workers:Web Workers 是 HTML5 中的一个新功能,通过将 JavaScript 运行在独立的线程中,可以释放浏览器主线程的负担,从而提高 JavaScript 的性能和效率。Web Workers 可以用于后台计算、大数据处理、网络请求等操作。但是需要注意的是,Web Workers 模型不能直接访问 DOM,需要采用消息传递机制来与主线程通信。