lznbuild / my-blog

自己的博客
9 stars 1 forks source link

性能优化 #37

Open lznbuild opened 4 years ago

lznbuild commented 4 years ago

性能标准

性能分析工具

chrome 工具中的memory Heap snapshot。其实就是当前页面的js对象及其相关的DOM节点的内存分布情况。 可以在内存泄露前生成一份堆快照,再在内存泄露后生成一份堆快照。通过对比的方式,找出两份堆快照存在的内存泄露点。最好是在一次操作后分析,以便分析出问题。

网上常见的性能优化方案,基本可以分为3类

好了,性能优化说完了。。。。

前两条,资源加载和渲染,可以一起说,这就避不开一个问题,就是从输入URL到页面加载完成,发生了什么,搞明白这个问题,才能有针对的优化。

这里只列出简易说明,详细请看 这里

这几个过程中可以进行优化的方向在括号中都已说明。 下面说下具体怎么做。

link标签有rel值,可以帮开发者做资源预加载。

rel值:

<link rel="dns-prefetch" href="//g.alicdn.com"> // 慎用,浏览器自己有自己的一套域解析方法 
<link rel="preload" href="/path/to/style.css" as="style">

使用http响应头的Link字段创建

Link: <https:/ /example.com/other/styles.css>; rel=preload; as=style

关于资源的预加载,要注意一点。加载资源可能会加长首屏渲染的时间,请谨慎使用。

关于网络请求这部分直接用http缓存就好,详情查看 这里

CDN

1.缩减用户和服务器的距离,提升加载效率

2.浏览器对一个域名的并发请求有限制,所以用cdn域名专门加载静态资源

比如项目中用到的echarts等第三方包,可以用cdn引入。

图片的优化

加载资源如果是图片的话,可针对图片进行优化。

使用base64的编码方式,对这个图片进行 Base64 编码,浏览器原来是可以理解这个字符串的,它自动就将这个字符串解码为了一个图片,而不需再去发送 HTTP 请求。用于小图 Base64 编码后,图片大小会膨胀为原文件的 4/3(这是由 Base64 的编码原理决定的)

jpeg,jpg, 体积小,加载快,不支持透明,用与大图,有损压缩,不好处理矢量图,颜色对比强烈的图

png 无损压缩,高保真,体积大,用于logo,图标,透明图

svg 体积小,灵活,矢量图不失真,可编程,渲染成本高

webp 体积和质量相对最平衡的一种图片类型

雪碧图 减少HTTP请求

关于图片除了使用合理文件类型,雪碧图,还可以通过image-webpack-loader压缩,减少体积。

服务端渲染

除了客户端渲染之外,还有另一种方案--服务端渲染。

客户端渲染模式下,服务端会把渲染需要的静态文件发送给客户端,客户端加载过来之后,自己在浏览器里跑一遍 JS,根据 JS 的运行结果,生成相应的 DOM。

服务端渲染的模式下,当用户第一次请求页面时,由服务器把需要的组件或页面渲染成 HTML 字符串,然后把它返回给客户端。客户端拿到手的,是可以直接渲染然后呈现给用户的 HTML 内容,不需要为了生成 DOM 内容自己再去跑一遍 JS 代码

搜索引擎只会查找现成的内容,不会帮你跑 JS 代码。

img中的alt属性是搜索引擎判断图片与文字是否相关的重要依据,优化搜索引擎.

服务端渲染本质上是本该浏览器做的事情,分担一部分给服务器去做。这样当资源抵达浏览器时,它呈现的速度就快了。乍一看好像很合理:浏览器性能毕竟有限,服务器多牛逼!能者多劳,就该让服务器多干点活!

但仔细想想,在这个网民遍地的时代,几乎有多少个用户就有多少台浏览器。用户拥有的浏览器总量多到数不清,那么一个公司的服务器又有多少台呢?我们把这么多台浏览器的渲染压力集中起来,分散给相比之下数量并不多的服务器,服务器肯定是承受不住的,所以需要合理使用服务端渲染。

解析资源

浏览器拿到资源后,进行解析资源的过程。

我们知道,只有当我们开始解析 HTML 后、解析到 link 标签或者 style 标签时,CSS 才登场,CSSOM 的构建才开始。很多时候,DOM 不得不等待 CSSOM。因此我们可以这样总结:

CSS 是阻塞渲染的资源。需要将它尽早、尽快地下载到客户端,以便缩短首次渲染的时间。

这个“把 CSS 往前放”的动作,对很多同学来说已经内化为一种编码习惯。那么现在我们还应该知道,这个“习惯”不是空穴来风,它是由 CSS 的特性决定的。

当渲染引擎解析 HTML 遇到 script 标签引入文件时,会立即进行一次渲染。所以这也就是为什么构建工具会把编译好的引用 JavaScript 代码的 script 标签放入到 body 标签底部,因为当渲染引擎执行到 body 底部时会先将已解析的内容渲染出来,然后再去请求相应的 JavaScript 文件。如果是内联脚本(即不通过 src 属性引用外部脚本文件直接在 HTML 编写 JavaScript 代码的形式),渲染引擎则不会渲染。

以上就说明了两点,css引入放开头,js引入放结尾。 js文件可以通过async,defer加载,避免阻塞dom树的解析。

关于渲染时的回流重绘

浏览器自己清楚,如果每次 DOM 操作都即时地反馈一次回流或重绘,那么性能上来说是扛不住的。于是它自己缓存了一个 flush 队列,把我们触发的回流与重绘任务都塞进去,待到队列里的任务多起来、或者达到了一定的时间间隔,或者“不得已”的时候,再将这些任务一口气出队。

当要用到像这样的属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 时,就要注意了!

这些值有一个共性,就是需要通过即时计算得到。因此浏览器为了获取这些值,也会进行回流。

除此之外,当我们调用了 getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发回流。原理是一样的,都为求一个“即时性”和“准确性”。

对于回流重绘,只能想办法减少次数。

具体的性能优化的方案

<script type="module" src="main.js"></script>
<script nomodule src="main.es5.js"></script>

支持type=module的浏览器,必然支持async/await promise, class 箭头函数 等等 而不支持 Githubissues.

  • Githubissues is a development platform for aggregating issues.