1.重绘与重排
重排(也叫回流)reflow/Relayout
当元素的尺寸、结构或触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。
浏览器渲染页面:浏览器渲染是基于“流式布局”的模型,流实际就使我们常说的文档流。浏览器根据渲染树中每个渲染对象的信息,计算出各自渲染对象的几何信息(DOM对象的位置和尺寸大小),并将其安置在界面中的正确位置。
会引起重排的操作有
- 页面首次渲染。
- 浏览器窗口大小发生改变。
- 元素尺寸或位置发生改变。
- 元素内容变化(文字数量或图片大小等等)。
- 元素字体大小变化。
- 添加或者删除可见的DOM元素。
- 激活CSS伪类(例如::hover)。
- 设置style属性
- 查询某些属性或调用某些方法。
重绘repaint
当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要UI层面的重新像素绘制,因此损耗较少。比如修改字体颜色、背景、边框类型、阴影、显隐等。
重排一定会重绘,重绘不一定有重排。
避免重排
- 避免设置大量的style属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性。
- 实现元素的动画,它的position属性,最好是设为absoulte或fixed,这样不会影响其他元素的布局。
- 动画实现的速度的选择。比如实现一个动画,以1个像素为单位移动这样最平滑,但是reflow就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
- 不要使用table布局,因为table中某个元素旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto;或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围。
- 如果在一个局部方法中需要多次访问同一个dom,则先暂存它的引用,避免多次访问dom。
- 少用DOM集合(类数组)来遍历,因为集合遍历比数组遍历耗费更高。
- 用事件委托来减少事件处理器的数量。
2. 你如何对网站的文件和资源进行优化?
- 文件合并(如js、css、图片) —css sprite
- 文件最小化/文件压缩
- 使用CDN托管
- 缓存的使用
- 减少重定向
- 减少dom节点数量
- 延迟载入组件或较大的资源文件
- 预加载较大的资源(预加载是异步非阻塞):
<link rel="preload" href="https://code.zuifengyun.com/2017/10/main.js" as="script" />
3.HTML和DOM的区别
- html是一种文档类型、是一种结构化文档、是一种标记语言。
- dom是具有一些API的文档对象模型(对象)。提供了一系列的对页面文档访问和操作的api。
- dom还可以操作其他的结构化文档,比如XML DOM 定义了一套标准的针对 XML 文档的对象。
4. 网页从输入网址到渲染完成经历了哪些过程?
大致可以分为如下7步:
- 输入网址;
- 发送到DNS服务器,并获取域名对应的web服务器对应的ip地址,如果做了CDN加速的话,会提供访问速度最快的 IP 地址;
- 浏览器通过IP与端口号与服务器建立TCP连接,会与服务器进行3次握手。
- 浏览器向web服务器发送http请求,请求方式如get/post/delete/put/option等。数据在进入服务端之前,可能还会先经过负责负载均衡的服务器或网关,它的作用就是将请求合理的分发到多台服务器或端口上或进行重定向。
- web服务器响应请求,并返回指定url的HTTP报文(或错误信息);
- 首先浏览器会判断返回的状态码是什么,如果是 200 那就继续解析,如果 400 或 500 的话就会报错,如果 300 的话会进行重定向,这里会有个重定向计数器,避免过多次的重定向,超过次数也会报错。
- 一次会话完成,关闭
- 浏览器解析源文件,如果是 gzip 格式的话会先解压一下,然后通过文件的编码格式知道该如何去解码文件。
- 解码完成后浏览器开始渲染流程,生成DOM树,解析css和js,渲染页面,直至呈现完成;(具体的渲染过程参考下文)
一文吃透浏览器渲染基本原理
5. 前端如何优化网站性能?
a.减少 HTTP 请求数量
在浏览器与服务器进行通信时,主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。HTTP1.1时代,浏览器通常有并行连接的限制,超过一定连接数量就会阻塞。因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
- CSS Sprites:国内俗称 CSS 精灵(雪碧图),这是将多张图片合并成一张图片达到减少 HTTP 请求的一种解决方案,可以通过 CSS background 属性来访问图片内容。这种方案同时还可以减少图片总字节数。
- 合并 CSS 和 JS 文件:现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
HTTP2.0多路复用允许单一的tcp连接发送多重http请求,这个连接可以承载任意数量的双向数据流,直观来说,就是上面我们所做的优化已经不需要了。
- 减少DNS查询时间,利用DNS预解析
- 使用CDN
- 利用浏览器缓存:传输轻量、细粒度的资源,以便独立缓存和并行传输。因为HTTP/2的多路复用和头部压缩特性。
- 最小化HTTP请求大小
- 最小化HTTP响应大小
- 减少不必要的重定向
- 服务端渲染:允许服务端主动发送额外的资源。类似于ssr首屏的处理。
- 采用 lazyLoad:俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容,节省了首屏加载的耗能。
- minify/gzip压缩,减小资源体积,使得加载更快。
- 预加载较大的资源或延迟加载。
rel="preload"
属性或defer
属性。 - 异步加载无需操作DOM的脚本,添加
async
属性。 - 脚本懒执行,某些脚本等到有需要的时候再执行。
b.控制资源文件加载优先级
浏览器在加载 HTML 内容时,是将 HTML 内容从上至下依次解析,解析到 link 或者 script 标签就会加载 href 或者 src 对应链接内容,为了第一时间展示页面给用户,就需要将 CSS 提前加载,不要受 JS 加载影响。
一般情况下都是 CSS 在头部,JS 在底部。
- 利用浏览器缓存:http缓存请求,离线缓存manifest,离线数据缓存localStorage
浏览器缓存是将网络资源存储在本地,等待下次请求该资源时,如果资源已经存在就不需要到服务器重新请求该资源,直接在本地读取该资源。 - 减少重排(Reflow)
基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。如果 Reflow 的过于频繁,CPU 使用率就会急剧上升。
c.减少 Reflow(重排/回流)
如果需要在 DOM 操作时添加样式,尽量使用 增加 class 属性,而不是通过 style 操作样式。
- 减少 DOM 操作
- 图标使用 IconFont 替换
d.加快请求速度
预解析DNS
你可以通过在服务器端发送 X-DNS-Prefetch-Control
报头,或是在文档中使用值为 http-equiv
的标签:
<meta http-equiv="x-dns-prefetch-control" content="off">
强制查询特定主机名
你可以通过使用 rel
属性值为 link type 中的 dns-prefetch
的 标签来对特定域名进行预读取:
<link rel="dns-prefetch" href="http://www.xxx.com/">
CDN分发
就近分配服务器,提高请求速度。
6.什么是同源策略?
两个页面地址中的协议、域名和端口号一致,则表示同源。
同源策略的限制:
- 存储在浏览器中的数据,如localStroage、Cooke不能通过脚本跨域访问
- 不能通过脚本操作不同域下的DOM
- 不能通过ajax请求不同域的数据
- 跨域请求不能携带cookie信息,需要配置响应头”Access-Control-Allow-Credentials”: true
为什么会有同源策略:
目的是为了安全,如果没有同源限制,在浏览器中的cookie等其他数据可以任意读取,不同域下的DOM任意操作,ajax任意请求其他网站的数据,包括隐私数据。
7. 什么是跨域,解决跨域所有方法
用ajax访问非同源的接口地址,或非同源的页面直接传递数据,就会存在跨域问题。
解决跨域的办法:
1.通过jsonp跨域
缺点:
只能使用Get请求
不能注册success、error等事件监听函数,不能很容易的确定JSONP请求是否失败
JSONP是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,其安全性无法确保
2.通过修改document.domain来进行跨域
缺点:只能跨子域
3.HTML5新引进的window.postMessage方法实现跨域传参
缺点:会阻断后续程序的执行。所以只能放到程序最后。
4.CORS跨域(常用),服务器返回数据时修改响应头,使浏览器认为是同源。
Access-Control-Allow-Origin: * //该字段必须,表示接受任意域名的请求
Access-Control-Allow-Methods: POST, GET, OPTIONS //必须,永续请求的方式
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type //可选,允许接受除了6个基本字段:
Cache-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
外的其他字段。Access-Control-Max-Age: 86400 //指定本次预检请求的有效期,单位为秒。一旦服务器通过了”预检”请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个
Origin
请求头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin
头信息字段。Access-Control-Allow-Credentials: true //允许浏览器发送cookie
详细信息如下文:
Access-Control-Allow-前后端设置跨域CORS详解
5.动态创建script,script标签不受同源策略的限制。具体没考究。
6.iframe中使用利用location.hash 跨域传值
7.web socket协议进行跨域,建立长连接可以跨域。服务器需要配置支持web socket协议。
8.使用网关做反向代理,借助中间层。如nginx反向代理,node中间层反向代理。
8.图片懒加载和预加载
预加载:提前加载图片,当用户需要时直接从缓存中渲染。预加载是为了避免图片的加载过慢造成较差的用户体验,但是会增加服务器前端的压力。
懒加载:当浏览器滚动到相应的位置时再渲染相应的图片。目的是优化前端压力,减少请求数或延迟请求。对服务器前端有一定缓解压力作用。但是若图片较大,则会带来较差的用户体验。
懒加载实现方法:
先将img
标签中的src
的路径设置为同一张图片(空白图片),将真正的图片路径保存在data-src
属性中,通过scrollTop
方法获取浏览器窗口顶部与文档顶部之间的距离,通过clientHeight
方法获取可视区高度。对window.scoll
触发时,执行事件载入data-src
(对每个img
标签DOM来求其offsetTop
,如果距离顶部的高度 >=可视区高度+窗口距离文档顶部的距离 )。
9.简单解释cookie和session
- cookie数据存放在本地浏览器,session数据存放在服务器。
- cookie并不是很安全,别人可以分析和修改cookie,考虑到安全赢个结合session使用。
- cookie结合session可以用来进行登陆或请求验证。session会保存到服务器上,有失效时间。cookie中保存session id
- 单个cookie数据不能超过4k,且很多浏览器限制了一个站点cookie的数量。比如20个。
- 由于安全性,现代ajax请求通常采用token方式取代cookie-session
10.异步加载js方式
① async属性
<script type="text/javascript" src="https://code.zuifengyun.com/2017/10/xxx.js" async="async"></script>
async
属性是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持async
属性规定一旦脚本可用,则会异步执行async
属性仅适用于外部脚本- 此方法不能保证脚本按顺序执行
- 他们将在onload事件之前完成
② defer属性
<script type="text/javascript" defer></script>
defer
属性规定是否对脚本执行进行延迟,直到页面加载为止- 如果脚本不会改变文档的内容,可将
defer
属性加入到<script>
标签中,以便加快处理文档的速度 - 兼容所有浏览器
- 此方法可以确保所有设置了
defer
属性的脚本按顺序执行 - 在IE中同时存在defer和async属性时,defer的优先级比较高
③ 异步创建script标签,插入到DOM
(function(){
var scriptEle = document.createElement("script");
scriptEle.type = "text/javasctipt";
scriptEle.async = true;
scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
var x = document.getElementsByTagName("head")[0];
x.insertBefore(scriptEle, x.firstChild);
})();
11. CDN是什么
CDN的全称是Content Delivery Network,即内容分发网络。其通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。 因为CDN的这些特性,我们可以将体积较大的文件或是图片上传到CDN中,通过CDN来加载,减轻了服务器的请求压力,同时也可以通过CDN来获取、加载依赖。