在前端面试中,有一道经典的面试题:请描述一下从url输入到页面渲染的过程。这道题很考察候选人的能力和知识深度, 今天咱们以这个问题为基础,讲一下在此过程当中能作哪些优化。css
首先作 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
详见Carlo大佬的博文 细说https
当发送http请求时,浏览器首先会按顺序检查如下四项是否存在缓存
MemoryCache,是指存在内存中的缓存。从优先级上来讲,它是浏览器最早尝试去命中的一种缓存。从效率上来讲,它是响应速度最快的一种缓存。浏览器秉承的是“节约原则”,咱们发现,Base64 格式的图片,几乎永远能够被塞进 memory cache,这能够视做浏览器为节省渲染开销的“自保行为”;此外,体积不大的 JS、CSS 文件,也有较大地被写入内存的概率——相比之下,较大的 JS、CSS 文件就没有这个待遇了,内存资源是有限的,它们每每被直接甩进磁盘。
Service Worker 是一种独立于主线程以外的 Javascript 线程。它脱离于浏览器窗体,所以没法直接访问 DOM。这样独立的个性使得 Service Worker 的“我的行为”没法干扰页面的性能,这个“幕后工做者”能够帮咱们实现离线缓存、消息推送和网络代理等功能。咱们借助 Service worker 实现的离线缓存就称为 Service Worker Cache。
它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的状况下,才会走协商缓存。
Push Cache 是指 HTTP2 在 server push 阶段存在的缓存。
关于浏览器的强缓存和协商缓存,详见Carry的博文 前端静态资源缓存
关于sevice Worker缓存, 详见Carry的博文 前端静态资源缓存之sevice worker
CDN 的核心点有两个,一个是缓存,一个是回源。
“缓存”就是说咱们把资源 copy 一份到 CDN 服务器上这个过程,“回源”就是说 CDN 发现本身没有这个资源(通常是缓存的数据过时了),转头向根服务器(或者它的上层服务器)去要这个资源的过程。
CDN 每每被用来存放静态资源。所谓“静态资源”,就是像 JS、CSS、图片等不须要业务服务器进行计算即得的资源。而“动态资源”,顾名思义是须要后端实时动态生成的资源,较为常见的就是 JSP、ASP 或者依赖服务端渲染获得的 HTML 页面。
那“非纯静态资源”呢?它是指须要服务器在页面以外做额外计算的 HTML 页面。具体来讲,当我打开某一网站以前,该网站须要经过权限认证等一系列手段确认个人身份、进而决定是否要把 HTML 页面呈现给我。这种状况下 HTML 确实是静态的,但它和业务服务器的操做耦合,咱们把它丢到CDN 上显然是不合适的。
另外,CDN的域名必须和主业务服务器的域名不同,要不,同一个域名下面的Cookie各处跑,浪费了性能流量的开销,CDN域名放在不一样的域名下,能够完美地避免了没必要要的 Cookie 的出现!
浏览器的渲染机制通常分为如下几个步骤:
在渲染dom的时候,浏览器实际上所作的工做是
CSS 是阻塞的资源。浏览器在构建 CSSOM 的过程当中,不会渲染任何已处理的内容。即使 DOM 已经解析完毕了,只要 CSSOM 不 OK,那么渲染这个事情就不 OK。咱们将 CSS 放在 head 标签里 和尽快 启用 CDN 实现静态资源加载速度的优化。 CSS 选择符是从右到左进行匹配的,好比 #myList li {}实际开销至关高。
JS 引擎是独立于渲染引擎存在的。咱们的 JS 代码在文档的何处插入,就在何处执行。当 HTML 解析器遇到一个 script 标签时,它会暂停渲染过程,将控制权交给 JS 引擎。
JS 引擎对内联的 JS 代码会直接执行,对外部 JS 文件还要先获取到脚本、再进行执行。等 JS 引擎运行完毕,浏览器又会把控制权还给渲染引擎,继续 CSSOM 和 DOM 的构建。
咱们将耗时的js操做放在页面的尾部,等待html和css渲染完毕再执行js防止js阻塞页面渲染。
JS中分为同步任务和异步任务,同步任务在执行栈中执行,异步任务的回调被放在任务队列中,等待执行栈空闲时执行。 setTimeout/setInterval,XHR/fetch的回调函数都属于异步任务。
任务栈执行一次的过程属于一次宏任务,在一个宏任务执行结果后,在下一个宏任务执行前,GUI渲染线程开始工做,对页面进行渲染。
微任务是在一次宏任务执行完毕以后,GUI线程执行以前执行的任务。当宏任务执行完,会在渲染前,将执行期间所产生的全部微任务都执行完. Promise,process.nextTick等,属于微任务
合理的安排宏任务微任务以及dom操做的顺序,能够尽量的减小无效的dom操做。
更多关于js和Event Loop的知识,请参考云中桥大佬的博文 从多线程到Event Loop全面梳理
回流:当咱们对 DOM 的修改引起了 DOM 几何尺寸的变化(好比修改元素的宽、高或隐藏元素等)时,浏览器须要从新计算元素的几何属性(其余元素的几何属性和位置也会所以受到影响),而后再将计算的结果绘制出来。这个过程就是回流(也叫重排)。
重绘:当咱们对 DOM 的修改致使了样式的变化、却并未影响其几何属性(好比修改了颜色或背景色)时,浏览器不需从新计算元素的几何属性、直接为该元素绘制新的样式(跳过了上图所示的回流环节)。这个过程叫作重绘。
重绘不必定致使回流,回流必定会致使重绘。回流比重绘作的事情更多,带来的开销也更大。在开发中,要从代码层面出发,尽量把回流和重绘的次数最小化。
负载均衡: session复制