前端性能优化总结(一)-js、css优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端性能优化总结(一)-js、css优化相关的知识,希望对你有一定的参考价值。

参考技术A 移动互联网时代,用户对于网页的打开速度要求越来越高。首屏作为直面用户的第一屏,其重要性不言而喻。优化用户体验更是我们前端开发非常需要 focus 的东西之一。

从用户的角度而言,当打开一个网页,往往关心的是从输入完网页地址后到最后展现完整页面这个过程需要的时间,这个时间越短,用户体验越好。所以作为网页的开发者,就从输入url到页面渲染呈现这个过程中去提升网页的性能。

所以输入URL后发生了什么呢?在浏览器中输入url会经历域名解析、建立TCP连接、发送http请求、资源解析等步骤。

http缓存优化是网页性能优化的重要一环,这一部分我会在后续笔记中做一个详细总结,所以本文暂不多做详细整理。本文主要从网页渲染过程、网页交互以及Vue应用优化三个角度对性能优化做一个小结。

首先谈谈拿到服务端资源后浏览器渲染的流程:

关键渲染路径是浏览器将 html、CSS、javascript 转换为在屏幕上呈现的像素内容所经历的一系列步骤。也就是我们刚刚提到的的的浏览器渲染流程。

为尽快完成首次渲染,我们需要最大限度减小以下三种可变因素:

首先,DOM 和 CSSOM 通常是并行构建的,所以 CSS 加载不会阻塞 DOM 的解析。

然而,由于 Render Tree 是依赖于 DOM Tree 和 CSSOM Tree 的,
所以他必须等待到 CSSOM Tree 构建完成,也就是 CSS 资源加载完成(或者 CSS 资源加载失败)后,才能开始渲染。因此,CSS 加载会阻塞 Dom 的渲染。

由此可见,对于 CSSOM 缩小、压缩以及缓存同样重要,我们可以从这方面考虑去优化。

当浏览器遇到 script 标记时,会阻止解析器继续操作,直到 CSSOM 构建完毕,JavaScript 才会运行并继续完成 DOM 构建过程。

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

回流(Reflow)
当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。现代浏览器会对频繁的回流或重绘操作进行优化:浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当你访问以下属性或方法时,浏览器会立刻清空队列:

因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。

避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
也可以先为元素设置 display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

图片懒加载在一些图片密集型的网站中运用比较多,通过图片懒加载可以让一些不可视的图片不去加载,避免一次性加载过多的图片导致请求阻塞(浏览器一般对同一域名下的并发请求的连接数有限制),这样就可以提高网站的加载速度,提高用户体验。

将页面中的img标签src指向一张小图片或者src为空,然后定义data-src(这个属性可以自定义命名,我才用data-src)属性指向真实的图片。src指向一张默认的图片,否则当src为空时也会向服务器发送一次请求。可以指向loading的地址。注意,图片要指定宽高。

当载入页面时,先把可视区域内的img标签的data-src属性值负给src,然后监听滚动事件,把用户即将看到的图片加载。这样便实现了懒加载。

事件委托其实就是利用JS事件冒泡机制把原本需要绑定在子元素的响应事件(click、keydown……)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
优点:

例如有一个列表需要绑定点击事件,每一个列表项的点击都需要返回不同的结果。
传统写法:

传统方法会利用for循环遍历列表为每一个列表元素绑定点击事件,当列表中元素数量非常庞大时,需要绑定大量的点击事件,这种方式就会产生性能问题。这种情况下利用事件委托就能很好的解决这个问题。

改用事件委托:

输入搜索时,可以用防抖debounce等优化方式,减少http请求;
这里以滚动条事件举例:防抖函数 onscroll 结束时触发一次,延迟执行

节流函数:只允许一个函数在N秒内执行一次。滚动条调用接口时,可以用节流throttle等优化方式,减少http请求;
下面还是一个简单的滚动条事件节流函数:节流函数 onscroll 时,每隔一段时间触发一次,像水滴一样

参考链接: https://zhuanlan.zhihu.com/p/113864878?from_voters_page=true

前端性能优化方法总结

0.前言

现今“前端”这个词涵盖的技术已经远不只HTML/CSS/JS了。我们先来看看数据的最长链路:

  1. 起点是浏览器地址栏输入框
  2. 浏览器缓存
  3. 浏览器网络请求
  4. 各级路由器和CDN
  5. Nginx或F5
  6. 网关缓存
  7. Node.js
  8. Node层缓存
  9. 静态文件读取/数据库读取/服务器渲染
  10. 返回响应通过各级路由器
  11. 浏览器发起预连接、预加载、子资源请求等
  12. 浏览器渲染
  13. JS执行引起更多网络请求和渲染

所以,每一个节点都是有优化空间的。

本文不会解释各个技术名词,请自行百度,同时也略过服务器硬件的优化。

1.地址栏的优化

  • 开启HSTS:如果全站都是HTTPS,使用HSTS不仅更安全,也减少一次HTTP 301跳转。
  • URL尽可能地短,包括域名。如果要做到SEO的keyword in url,那就只放重要的keyword即可。

2.网络层优化

  • 非安全性敏感页面和资源,使用HTTP协议即可,减少加解密过程的消耗。
  • 对静态资源设置HTTP缓存并使Max-Age尽可能长,减少浏览器发起的请求数。子资源如CSS、JS等可在文件名或query中加入版本号/时间戳/hash值,然后把缓存期限设到最大。
  • 开启Etag
  • 使用ServiceWorker的Cache API提前缓存资源
  • 使用dns-prefetch、preconnect、prefetch提示浏览器做预处理
  • 开启压缩,并覆盖尽可能多的mime type。Brotli优于Gzip。
  • 启用CDN。条件许可的话可自行预热或保持热度,减少CDN的回源。
  • 使用开源代码的免费CDN时,选择高速的。如果要做SEO,那选百度的为佳。
  • 启用HTTP2,在中高速网络下,单个连接完成数据传输的效率更高。
  • 减少内网的中间节点
  • 公网出口的Http Server用最高速的实现。软件是Nginx,硬件是F5等。
  • 使用服务质量高的DNS服务商,降低DNS过程的延时和错误率。
  • DNS设置较长的TTL
  • 各级服务器内存缓存设置足够大

3.Nginx配置优化

  • 足够多的进程
  • 足够大的内存缓存设置
  • 负载均衡
  • API请求,不同域名时,服务器直接支持跨域优于Nginx反向代理。
  • 关闭冗余的header信息

4.HTML/CSS/JS优化

  • 减少DOM数量和层级。确保语义清晰的前提下使用尽可能少的标签。
  • 资源懒加载、延时加载
  • 去掉log,debugger
  • 去掉埋点或使用beacon等高级方法来做埋点
  • 1KB以下的图片使用base64做内联
  • 图片预压缩,然后nginx关闭对图片做压缩。不关闭可能会更慢。
  • 图片做好不同分辨率的副本(包括缩略图),按需要选择显示。
  • 缓存后端数据。MPA可使用cookie、local/session storage等方式,SPA可利用框架缓存在内存。
  • 内联CSS、JS小文件
  • JS、CSS最小化
  • 合并CSS、JS文件,减少网络请求。
  • CSS Sprite。合并多个小图到一张大图里,通过定位显示指定图片,减少网络请求
  • 在<head></head>标签内的外部JS加上async属性
  • 在靠近</body>的地方加载外部JS。这些JS不应该引起渲染更新
  • 所有文件的命名里禁止使用广告拦截插件的黑名单关键字,例如ad、adv、advertise等
  • JS使用高效的API,例如字典的遍历操作使用for...of最快。
  • 少使用第三方库,能用原生实现就用原生,或只用必须依赖的库的API
  • 自己精简第三方库,去掉用不着的部分
  • 使用CSS3动画代替JS Timer类动画
  • 无限的瀑布流,回收利用DOM节点,或只置空远离屏幕外的img src。
  • 信息流做分页加载
  • canvas:离屏渲染、缓存。
  • 合理设计DOM层次,会被JS频繁操作的地方不要引起大范围的重排版。
  • 跨整站使用的代码,抽出来单独加载。
  • 单页面应用SPA,开启分包
  • 减少资源的链式依赖
  • webp的使用
  • 合理选择浏览器的兼容范围。这会影响到js的polyfill和css的verdor prefix。

5.Node.js优化

  • 开启足够多的进程。
  • 根据UA做好浏览器判断,可在渲染结果中减少一些为了兼容性而存在的代码。记得在响应header中加上vary。
  • Java或PHP后端做的优化,用Node.js实现时也可以做。比如SQL优化,Redis、MQ的使用等。
  • 模板缓存
  • 减少、合并cookie数据
  • 静态文件直接用nginx托管

 

以上是关于前端性能优化总结(一)-js、css优化的主要内容,如果未能解决你的问题,请参考以下文章

前端性能的优化总结

如何对前端性能进行优化

前端性能优化

前端性能优化方法总结

前端性能优化

前端开发代码结构及性能优化大总结