前端性能优化

二叶草 2020年2月3日22:12:47优化评论阅读模式

前言

随着 Web 应用在市面上越来越广泛,互联网技术越来越娴熟,用户对应用的要求也不再是简单的实现功能,更重要的是响应速度。比如首屏响应速度,比如页面交互时间,都是用户决定一个应用好坏的最直观标准,通常一个 web 项目性能取决于前后端包括硬件设施等各方面的共同作用,那么作为一名前端开发人员,可以做些什么?将是本文探讨的主题,通过简单梳理,可以从以下五个方面思考。

一、代码优化

  1. 减少 css 层级嵌套,在解析 CSSOM 规则树的时候使用的是递归,所以嵌套得越少,效率越高;

  2. 避免使用 css 表达式,css 表达式最早是从微软的 IE5.0 开始,目的是可以动态地设置样式,但是这种写法极度消耗性能,一个简单的表达式会执行上千次,严重影响浏览器性能,所以从 IE5.0 开始就终止了这种功能的使用。并且其他浏览器和 w3c 标准组织也不支持这种方式。

  3. 少用全局变量,全局变量会造成全局污染,内存泄漏;

  4. 多个声明放在一起,使用较少的 var 关键字,将多个声明放在一起,加快脚本执行时间,如 var a=1;var b=2 可写成 var a=1,b=2;

  5. 使用 DocumentFragment,DocumentFragment 是文档片段接口,因为不是真实 DOM 树的一部分,所以使用它不会引起回流,因此不会导致性能问题, 使用代码片段接收 DOM 对象,等到 DOM 对象组装完成,再将代码片段插入到 DOM 节点;

//动态插入 li 标签
var documentFragment = document.createDocumentFragment();
for (var i = 0; i < 20; i++) {
var li = document.createElement('li');
li.textContent = i;
documentFragment.appendChild(li);
}
document.body.appendChild(documentFragment);

DocumentFragment 相当于是一种占位符,将 20 个 li 节点插入到 DocumentFragment 中,最后再将 DocumentFragment 插入到 body 中,这样就只需要一次渲染页面,大大减少 DOM 操作。

  1. 使用事件委托,将事件委托给父元素;

  2. css 样式表放在 body 头部,js 脚本放在 body 底部,css 样式放在 body 头部,优先加载,避免出现因 js 加载阻塞导致空白页;

  3. 避免重定向,一次重定向至少需要耗时 600ms;

  4. 尽量少的操作 DOM 节点,许多 DOM 操作,比如改变浏览器窗口大小,页面大小,字体大小,页面定位,布局等都会导致回流,即页面重构。所以应该尽可能的减少 DOM 操作;

  5. 延迟加载,加快首屏加载时间,比如在首屏刚开始使用小图片,使用户觉得页面已加载完成,再通过条件判断,逐步加载大图片;

  6. 尽量使用 css 动画,避免使用 js 动画,使用 css 动画时,有3大优势,1)浏览器使用与 requestAnimationFrame 类似的机制,把每一帧中的所有 DOM 操作集中起来进行一次重绘或回流;2)在隐藏或不可见的元素中 requestAnimationFrame 不会进行重绘或回流,这意味着减少了 CPU、GPU 和内存的使用;3)强制使用硬件加速 (通过 GPU 来提高动画性能)。而 javaScript 是在浏览器的主线程中运行,主线程中有其他的脚本执行,样式计算,布局绘制等,会影响动画执行,导致可能会出现掉帧现象。

  7. 使用 requestAnimation 代替 setTimeout,一般浏览器显示的频率是 16.7ms(1000/60)即每秒 60 帧,如果超过这个时间,就会出现掉帧的现象,而 requestAnimation 是根据浏览器的节奏绘制的,即浏览器设备绘制间隔时间是多久,requestAnimation 就多久进行绘制,所以动画会比较流畅。

  8. 长列表滚动优化,在移动端的屏幕滚动中,需要给 body 添加上-webkit-overflow-scrolling: touch 来使 IOS 滚动更流畅。长列表滚动时,会频繁操作 DOM,不断增加 DOM 节点,影响性能,现在市面上有两种解决方案,1)对用户不可见区域,即已经加载过的 DOM 节点进行删除,这种方案的弊端是如果操作太快,会导致白屏现象;2)对 DOM 进行复用。

  9. 节流与防抖,滚动必将会频繁的操作 DOM,节流与防抖都是为了限制频繁的操作,以防因操作过于频繁而导致响应跟不上,出现延迟、卡顿的现象。 节流是预先设计好一个执行周期,当操作的时间在周期内,则执行,否则进入下一个周期。防抖是将频繁的调用动作控制在一定时间内,如果在此时间内又调用则重新计算时间。

二、减少 http 请求

  1. 减少空的 src 属性和 href 属性,因为空属性也会使页面重新加载;

  2. 使用 css sprites 背景图,减少图片请求,也就是所谓的雪碧图,将图片,主要是小图标集中放在一张图片上面,通过设置 css 背景图属性添加图片;

  3. 使用 data url 代替图片 src;

  4. 脚本合并,单页面应用通过 webpack 打包之后通常只有一个 js,但是多页面应用会有多个 js 请求,如果能有效的将 js 脚本合并,就能减少脚本请求次数。

三、缓存优化

1. HTTP 缓存
浏览器缓存分为强制缓存与协商缓存。

  • 强缓存
    在谷歌浏览器控制台的 network 选项中,如果 Status 状态是 200,Size 是 from memory cache 或者 from disk cache 就是强制缓存。强制缓存的报文头信息如下:
    1)Expires:HTTP1.0 出现的缓存头,由服务器设置一个缓存时间,浏览器在请求时,会检查这个时间,如果没过期,则直接返回浏览器的缓存内容,不会发送请求。对于图片可以设置一个长时间的 Expires 头,因为图片短时间内不会改变。Expires 的缺点是本地时间与服务器时间有可能不一致。
    2)Cache-Control:HTTP1.1 出现的缓存头,这是一个相对时间,以秒为单位,用数值表示,如果设置 max-age=600,则在10分钟之内重新发起请求就会命中强缓存。
    3)两者差别:一个是HTTP1.0 出现的,一个是HTTP1.1 出现的,如果两者同时存在时,Cache-Control 优先级更高,Expires 只是为了做兼容。
    4)缺陷:只关心时间是否过期,但是对内容是否发生变化却无法得知。

  • 协商缓存
    浏览器发送请求,服务器会根据请求头信息来判断是否命中协商缓存,如果命中,则直接返回 304 状态码并带上新的请求头信息告知浏览器从缓存中读取资源,协商缓存的报文头信息如下:
    1)Last-Modified:设置这个标记会通知浏览器可以使用 If-Modified-Since 头来产生一个条件 GET 请求以便检查其本地缓存时间。如果数据不需要更新,服务器将使用 HTTP 304 状态码来响应此请求。Last-Modified 的缺点是只能精确到1秒钟,如果在1秒钟以内修改,也会被缓存。
    2)Etags:即 Entity Tag,意思是实体标签,从名字上看,是对于某种实体的一个标识。它属于 HTTP 协议的一部分,也就是所有的 Web 服务器都应该(也确实能)支持这个特性。它的作用是根据一定的算法生成 hash 值来作为某个资源的唯一标识,只要资源发生变化,Etags 就会重新生成,浏览器在下一次加载资源时会将上一次返回的 Etags 值放在 If-None-Match 中,服务器判断 Etags 是否一致,如果一致,则返回 304 状态码,告知浏览器读取缓存,反之则将最新的资源返回到浏览器。
    3)两者差别:Last-Modified 只能精确到秒,而 Etags 只要文件修改了,都会改变。其次因为 Last-Modified 只需要记录时间,而 Etags 时根据算法计算 hash 值,所以前者性能优于后者。Etags 的优先级高于 Last-Modified。

  • HTTP 请求过程总结
    1)浏览器请求资源;
    2)查看是否有强缓存,即 Cache-Control 与 Expires 时间是否过期;
    3)如果没有过期,则直接读取资源;
    4)如果时间过期,查看内容是否过期,即携带标识(If-None-Match 与 If-Modified-Since)向服务器发送请求;
    5)服务器检查资源是否有更新;
    6)如果没有更新,返回 304 状态码,告知浏览器继续使用缓存;
    7)如果过期,则返回最新资源,返回 200 状态码。

2. 本地缓存

  • Cookies:存储数据有限,每次请求都会带完整的带到服务器,占用带宽。

  • sessionStorage:临时存储,关闭浏览器后会清掉缓存。

  • localStorage:永久存储,有大小限制,数据不安全,不应该存重要的数据。

  • IndexedDB:持续化存续,可在 Web Worker 中使用。

3. 减少 DNS 查找
DNS用于映射主机名和 IP 地址,一般一次解析需要20~120毫秒。为达到更高的性能,DNS 解析通常被多级别地缓存,如由 ISP 或局域网维护的 caching server,本地机器操作系统的缓存(如windows上的DNS Client Service),浏览器。IE 的缺省 DNS 缓存时间为30分钟,Firefox 的缺省缓冲时间是1分钟。减少主机名可减少 DNS 查询的次数,但可能造成并行下载数的减少。避免 DNS 查找可减少响应时间,而减少并行下载数可能增加响应时间。一个可行的折中是把内容分布到至少2个,最多4个不同的主机名上。

四、压缩优化

1. CSS、JavaScript 压缩。

压缩目的:

  • 删除注释和空格等不必要的字符。

  • 删除多余的没用属性;

  • 将函数名和变量名替换成短的字符串。

压缩工具:

  • JSMin:由 Douglas Crockford (《JavaScript语言精粹》作者)开发

  • YUI Compressor在线:雅虎前端团队用 Java 开发制作的 JS/CSS 在线压缩工具

  • Packer:Dean Edwards 开发

2. 页面元素压缩

通过压缩HTTP响应内容可减少页面响应时间。从 HTTP/1.1 开始,Web 客户端在 HTTP 请求中通过 Accept-Encoding 头来表明支持的压缩类型,如:Accept-Encoding: gzip, deflate。
如果 Web server 检查到 Accept-Encoding 头,它会使用客户端支持的方法来压缩 HTTP 响应,会设置 Content-Encoding头,如:Content-Encoding: gzip。
Gzip 是目前最流行及有效的压缩方法。其他的方式如 deflate,但它效果较差,也不够流行。通过 Gzip,内容一般可减少70%。如果是 Apache,在1.3版本下需使用 mod_gzip 模块,而在2.x版本下,则需使用 mod_deflate。
Web server 根据文件类型来决定是否压缩。大部分网站对 HTML 文件进行压缩。但对脚本文件和样式表进行压缩也是值得的。实际上,对包括 XML 和 JSON 在内的任务文本信息进行压缩都是值得的。图像文件和 PDF 文件不应该被压缩,因为它们本来就是压缩格式保存的。对它们进行压缩,不但浪费 CPU,而且还可能增加文件的大小。
因此,对尽量多的文件类型进行压缩是一种减少页面大小和提高用户体验的简便方法。

3. 图片压缩

 

图片优化要点:

  • 图片不宽于 640px

  • 首次加载不大于 1014kb

  • webP 格式优于 JPG

  • PNG8 格式优于 GIF

  • 使用base64表示简单的图片

五、使用 CDN 加速

CDN(Content Delivery Network) 即内容分发网络,其核心是通过中心平台将内容分发给离用户最近的边缘服务器,再由边缘服务器响应用户,使用户能就近获取资源,从而避免网络拥堵,提交用户访问速度。

基本原理:

CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。

基本思路:

基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。

 

本文来源于:前端性能优化-变化吧门户
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧门户观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

在寻找靠谱的建站服务?

提供建站全方位托管服务,告诉我你的需求,剩下的交给我帮你处理,建站过程中碰到的任何小问题免费处理,网站所有数据由你自己掌握,还提供网站SEO指导,犹豫什么呢?联系我吧。

 

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
二叶草
nginx解析漏洞 优化

nginx解析漏洞

phpstudy(小皮模板存在nginx解析漏洞) 影响版本 phptsuy8.1.07的Nginx1.5.11版本影响版本 phptsuy8.1.07的Nginx1.5.11版本 phpstudy介...
网站SEO优化基础流程(新手必看) 优化

网站SEO优化基础流程(新手必看)

宝塔面板搭建一个获取网站的Favicon图标的APIgetFavicon是一个可以获取网站的Favicon图标并显示在你的网页上的项目。安装方法很简单,属于开箱即食。这篇文章还是基于宝塔面板来搭建。 ...

发表评论