从url到页面渲染:咱们能作哪些优化

在前端面试中,有一道经典的面试题:请描述一下从url输入到页面渲染的过程。这道题很考察候选人的能力和知识深度, 今天咱们以这个问题为基础,讲一下在此过程当中能作哪些优化。css

从输入 URL 到页面加载完成的过程

  • 首先作 DNS 查询,若是这一步作了智能 DNS 解析的话,会提供访问速度最快的 IP 地址回来html

  • 接下来是 TCP 握手,应用层会下发数据给传输层,这里 TCP 协议会指明两端的端口号,而后下发给网络层。网络层中的 IP 协议会肯定 IP 地址,而且指示了数据传输中如何跳转路由器。而后包会再被封装到数据链路层的数据帧结构中,最后就是物理层面的传输了前端

  • TCP 握手结束后会进行 TLS 握手,而后就开始正式的传输数据面试

  • 数据在进入服务端以前,可能还会先通过负责负载均衡的服务器,它的做用就是将请求合理的分发到多台服务器上,这时假设服务端会响应一个 HTML 文件后端

  • 首先浏览器会判断状态码是什么,若是是 200 那就继续解析,若是 400 或 500 的话就会报错,若是 300 的话会进行重定向,这里会有个重定向计数器,避免过屡次的重定向,超过次数也会报错浏览器

  • 浏览器开始解析文件,若是是 gzip 格式的话会先解压一下,而后经过文件的编码格式知道该如何去解码文件缓存

  • 文件解码成功后会正式开始渲染流程,先会根据 HTML 构建 DOM 树,有 CSS 的话会去构建 CSSOM 树。若是遇到 script 标签的话,会判断是否存在 async 或者 defer ,前者会并行进行下载并执行 JS,后者会先下载文件,而后等待 HTML 解析完成后顺序执行,若是以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。遇到文件下载的会去下载文件,这里若是使用 HTTP 2.0 协议的话会极大的提升多图的下载效率。安全

  • 初始的 HTML 被彻底加载和解析后会触发 DOMContentLoaded 事件服务器

  • CSSOM 树和 DOM 树构建完成后会开始生成 Render 树,这一步就是肯定页面元素的布局、样式等等诸多方面的东西网络

  • 在生成 Render 树的过程当中,浏览器就开始调用 GPU 绘制,合成图层,将内容显示在屏幕上了

http优化

增长安全性:用https代替http

http详解

http是超文本传输协议,可是在信息传输过程当中,因为通讯使用的是明文,可能存在信息被窃取和篡改的问题。

可使用安全的https替代http

详见Carlo大佬的博文 细说https

减小请求次数:浏览器缓存策略

当发送http请求时,浏览器首先会按顺序检查如下四项是否存在缓存

  • Memory Cache
  • Service Worker Cache
  • HTTP Cache
  • Push Cache

MemoryCache

MemoryCache,是指存在内存中的缓存。从优先级上来讲,它是浏览器最早尝试去命中的一种缓存。从效率上来讲,它是响应速度最快的一种缓存。浏览器秉承的是“节约原则”,咱们发现,Base64 格式的图片,几乎永远能够被塞进 memory cache,这能够视做浏览器为节省渲染开销的“自保行为”;此外,体积不大的 JS、CSS 文件,也有较大地被写入内存的概率——相比之下,较大的 JS、CSS 文件就没有这个待遇了,内存资源是有限的,它们每每被直接甩进磁盘。

Service Worker Cache

Service Worker 是一种独立于主线程以外的 Javascript 线程。它脱离于浏览器窗体,所以没法直接访问 DOM。这样独立的个性使得 Service Worker 的“我的行为”没法干扰页面的性能,这个“幕后工做者”能够帮咱们实现离线缓存、消息推送和网络代理等功能。咱们借助 Service worker 实现的离线缓存就称为 Service Worker Cache。

HTTP Cache

它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的状况下,才会走协商缓存。

Push Cachae

Push Cache 是指 HTTP2 在 server push 阶段存在的缓存。

  • Push Cache 是缓存的最后一道防线。浏览器只有在 Memory Cache、HTTP Cache 和 Service Worker Cache 均未命中的状况下才会去询问 Push Cache。
  • Push Cache 是一种存在于会话阶段的缓存,当 session 终止时,缓存也随之释放。
  • 不一样的页面只要共享了同一个 HTTP2 链接,那么它们就能够共享同一个 Push Cache。

关于浏览器的强缓存和协商缓存,详见Carry的博文 前端静态资源缓存

关于sevice Worker缓存, 详见Carry的博文 前端静态资源缓存之sevice worker

减小单次请求所花费的时间: CDN

CDN 的核心点有两个,一个是缓存,一个是回源。

“缓存”就是说咱们把资源 copy 一份到 CDN 服务器上这个过程,“回源”就是说 CDN 发现本身没有这个资源(通常是缓存的数据过时了),转头向根服务器(或者它的上层服务器)去要这个资源的过程。

CDN 每每被用来存放静态资源。所谓“静态资源”,就是像 JS、CSS、图片等不须要业务服务器进行计算即得的资源。而“动态资源”,顾名思义是须要后端实时动态生成的资源,较为常见的就是 JSP、ASP 或者依赖服务端渲染获得的 HTML 页面。

那“非纯静态资源”呢?它是指须要服务器在页面以外做额外计算的 HTML 页面。具体来讲,当我打开某一网站以前,该网站须要经过权限认证等一系列手段确认个人身份、进而决定是否要把 HTML 页面呈现给我。这种状况下 HTML 确实是静态的,但它和业务服务器的操做耦合,咱们把它丢到CDN 上显然是不合适的。

另外,CDN的域名必须和主业务服务器的域名不同,要不,同一个域名下面的Cookie各处跑,浪费了性能流量的开销,CDN域名放在不一样的域名下,能够完美地避免了没必要要的 Cookie 的出现!

渲染优化

浏览器的渲染机制通常分为如下几个步骤:

  • 处理 HTML 并构建 DOM 树。
  • 处理 CSS 构建 CSSOM 树
  • 将 DOM 与 CSSOM 合并成一个渲染树。
  • 根据渲染树来布局,计算每一个节点的位置。
  • 调用 GPU 绘制,合成图层,显示在屏幕上

在渲染dom的时候,浏览器实际上所作的工做是

  • 获取DOM后分割为多个图层
  • 对每一个图层的节点计算样式结果(Recalculate style–样式重计算)
  • 为每一个节点生成图形和位置(Layout–回流和重布局)
  • 将每一个节点绘制填充到图层位图中(Paint Setup和Paint–重绘)
  • 图层做为纹理上传至GPU
  • 复合多个图层到页面上生成最终屏幕图像(Composite Layers–图层重组)

服务端渲染

css优化建议

CSS 是阻塞的资源。浏览器在构建 CSSOM 的过程当中,不会渲染任何已处理的内容。即使 DOM 已经解析完毕了,只要 CSSOM 不 OK,那么渲染这个事情就不 OK。咱们将 CSS 放在 head 标签里 和尽快 启用 CDN 实现静态资源加载速度的优化。 CSS 选择符是从右到左进行匹配的,好比 #myList li {}实际开销至关高。

  • 避免使用通配符,只对须要用到的元素进行选择。
  • 关注能够经过继承实现的属性,避免重复匹配重复定义。
  • 少用标签选择器。若是能够,用类选择器替代。错误:#dataList li{} 正确:.dataList{}
  • 不要多此一举,id 和 class 选择器不该该被多余的标签选择器拖后腿。错误:.dataList#title 正确:#title
  • 减小嵌套。后代选择器的开销是最高的,所以咱们应该尽可能将选择器的深度降到最低(最高不要超过三层),尽量使用类来关联每个标签元素。

js阻塞和Event Loop

JS 引擎是独立于渲染引擎存在的。咱们的 JS 代码在文档的何处插入,就在何处执行。当 HTML 解析器遇到一个 script 标签时,它会暂停渲染过程,将控制权交给 JS 引擎。

JS 引擎对内联的 JS 代码会直接执行,对外部 JS 文件还要先获取到脚本、再进行执行。等 JS 引擎运行完毕,浏览器又会把控制权还给渲染引擎,继续 CSSOM 和 DOM 的构建。

咱们将耗时的js操做放在页面的尾部,等待html和css渲染完毕再执行js防止js阻塞页面渲染。

js 宏任务和微任务

  • JS中分为同步任务和异步任务,同步任务在执行栈中执行,异步任务的回调被放在任务队列中,等待执行栈空闲时执行。 setTimeout/setInterval,XHR/fetch的回调函数都属于异步任务。

  • 任务栈执行一次的过程属于一次宏任务,在一个宏任务执行结果后,在下一个宏任务执行前,GUI渲染线程开始工做,对页面进行渲染。

  • 微任务是在一次宏任务执行完毕以后,GUI线程执行以前执行的任务。当宏任务执行完,会在渲染前,将执行期间所产生的全部微任务都执行完. Promise,process.nextTick等,属于微任务

合理的安排宏任务微任务以及dom操做的顺序,能够尽量的减小无效的dom操做。

更多关于js和Event Loop的知识,请参考云中桥大佬的博文 从多线程到Event Loop全面梳理

回流和重绘

  • 回流:当咱们对 DOM 的修改引起了 DOM 几何尺寸的变化(好比修改元素的宽、高或隐藏元素等)时,浏览器须要从新计算元素的几何属性(其余元素的几何属性和位置也会所以受到影响),而后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。

  • 重绘:当咱们对 DOM 的修改致使了样式的变化、却并未影响其几何属性(好比修改了颜色或背景色)时,浏览器不需从新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。这个过程叫作重绘。

重绘不必定致使回流,回流必定会致使重绘。回流比重绘作的事情更多,带来的开销也更大。在开发中,要从代码层面出发,尽量把回流和重绘的次数最小化。

负载均衡: session复制

相关文章
相关标签/搜索