资讯专栏INFORMATION COLUMN

说下性能优化

王伟廷 / 3227人阅读

摘要:性能优化追求的是什么是你的网页可以以最快的速度打开比如说用户点一下啪的就开了点哪里哪里开什么操作都是立刻有反馈关键字是速度试想未来有一天到了时代每个人的网速都是的那你还优化什么你的网站就算是大小也不怕可是那是遥远的未来当下网速还没有这么快。

性能优化

追求的是什么, 是你的网页可以 以最快的速度 打开, 比如说用户点一下啪的就开了
点哪里哪里开, 什么操作都是立刻有反馈.

关键字是:速度

试想未来有一天, 到了 18G 时代, 每个人的网速都是 1000M 的, 那你还优化什么
你的网站就算是 100M 大小也不怕.

可是那是遥远的未来, 当下网速还没有这么快。

所以我们的问题是: 在一个比较低一点的网速上面, 尽可能的快的加载出来我们的页面.

固定一个变量: 网速.

所以问题变成: 在固定网速为 p 的条件下, 如何尽可能的让我们的页面快一点加载出来.
假设我们的资源大小是 n, 网速为 p, 理论上将资源, 从服务器拿到客户端需要的时间
是:

time = n/p

p 固定, 那么 n 越小, time 越小.
也就是说: 我们的资源的体积越小, 时间越短.

所以问题变成: 如何减少我们资源的大小?
先说我们的资源的种类有哪些?

images
js
css
html
fonts
others

依次看看怎么减小它们的体积:

图片压缩
js 压缩
css 压缩
html 压缩
fonts 删减
others 不知道

这些都是建立在你当前已经存在的资源的上面, 还可以做预处理:

切图的时候就不要切高清无码图

不要引入没有必要的 js, 或者说你为了兼容 Object.assign() 直接引了一个 babel-polyfill这样

不要闭着眼就把 bootstrap 引入进来了
...

上面的讨论, 实际上都是有一个前提的, 就是说:
所有的资源都从 server 到 client 之后, client 才能看见页面

但是这并不是真的:
有时只要你拿回来一部分资源的时候, 页面就可以显示出来了.
所以我们可以对资源做一些区分, 将 "页面显示出来所需要的最小资源集合" 优先返回回去,
剩下的资源再说, 这样也是一种思路。

所以我们的问题变成: 找到那个最小的资源集合, 或者说, 合理的安排资源的顺序。
how?

依旧是那些资源类型:

images
js
css
html
fonts
others

images 完全可以做懒加载, 不需要那么早就扔出去. 
第一次要展示的页面是 pageA, 那么 pageB 相关的资源, 你就不要先返回啊.

这方面相关的一些概念是:

首屏渲染

按需加载

code spliting

critial css

...

其实这句话说的好像是 server 去安排资源的顺序一样, 但是你也知道不是的, server说我就是无脑
扔, 你自己安排。
所以我们才会去让 link 提前加载, 让 script 在后面加载.

上面算是第一个阶段的结束, 现在我们更进一步
前面说了:

time = 资源大小 / 网速

实际上这个模型可以比喻成这样:
小明从 A 点到 B 点拿一堆总重量为 100kg 的东西, 小明需要多久才能把东西全部从 B ->A?
和小明每次拿多少, 以及他一趟要多久相关, 是不是?
所以上面提及到的 "网速" 这个概念, 是一个混合变量

"网速" = ("带宽","请求相应时间")

带宽, 也就是每次拿多少, 一般都是假设是一个固定的值
那么就剩下请求响应时间了, 这个涉及到的点,
就是: 接口响应要快.

前面讨论的时候, 都是假设, 只有小明一个人在搬, 但是如果有 10个人呢?
这里涉及到的就是:
浏览器的并行加载

这玩意是浏览器提供的, 我们谈我们的性能优化手段, 貌似和他也没有关系, 这个是浏览器做的事情.
不不不, 我们可以利用.
从这个角度来看, 是不是并行加载的数量越多越好? 就是的.
那么我们可以尝试去提高并行加载的数量啊, 比如说从 1 提高到 100
这里涉及到的是:
浏览器的并行加载是以 domain 为区分而限制的, 一个 domain 最多可以支持 4个(不同浏览器不同)
并行加载.

那么我们把资源分成多个域名不就可以了吗? 好像是这个道理.
你有100个资源, 划分成 25个域名, 同一个域名下面支持 4个并行, 那你不是一瞬间100个都发出去了吗
那速度不是唰的一下就上来了吗? (这块没弄明白)

那再想想, 还有什么办法能让时间更短一点?
让 A 跟 B 近一点啊.
这个就是 CDN.
也就是说, 我们可以上 CDN, 这个的确是我们做的.

上面的都是说第一次加载, 第一次访问的时候, 还有第二次第三次访问的情况, 这个时候就涉及到缓存了。

我们说下缓存
以我记忆里面的概念, 在性能优化的时候提到的缓存一般有三种情况:

浏览器缓存

通过使用 storage 进行缓存

Ajax 缓存

为什么要缓存?
因为当你第一次访问一个网站, 请求了 100个资源.
然后你第二次又访问了这个网站, 又请求了 100个资源.

把这两个 "100个资源"做并集, 就会发现并集里面有很多资源.
也就是说你在两次访问这个网站的时候, 对于同一个资源, 你请求了两次.
这肯定是不必要的, 浪费的. 所以我们完全可以搞起来.

怎么搞?

拿到多次访问的时候, 每次请求的资源, 作为一个集合

做这些集合的并集

得到的集合, 就是在这多次访问中都没有变化的资源, 称为 A

我们的目标就是: 让 A 中所有的资源都仅仅请求一次就好了.
1 得到 A
我们要怎么得到 A ? 资源是我们弄出来的啊, 代码是你写的,
你对资源都很清楚的, 所以你自己就知道哪些资源是一直都不变的, 哪些资源是一段时间就变的
哪些是每次都变的, 你很清楚啊.

好吧, 那我给你一个所有的不变的资源 A

2 再说下缓存是谁缓存? 浏览器啊, 那浏览器怎么知道这一堆资源里面哪个要缓存, 哪个不要?
你知道, 所以你要去告诉他.
你怎么告诉他? http 协议啊, 那只能是 http headers 字段里面标记了啊.
这里不具体说 协议头长什么样子, 说下方案:

server 告诉 client, 这个文件要缓存, 这个文件什么时候过期
在下一次访问的时候, 浏览器请求的时候呢发现了这个文件, 看看它什么时候过期, 发现没有过期
那就用, 哎一发现过期了, 那么就去重新请求. 就是保质期的意思.

第二种方案是 storage 做缓存, 我印象中记得看见过两个:
微信
美团的 LsLoader

第三种就是 Ajax 请求缓存, 通常见于 query 类型的接口的缓存, 比如说商品列表等.

最后一个讨论点, 我们之前只是说资源拿回来, 页面显示, 但是这两者之间, 还有个事情:
浏览器需要去渲染资源

我们说浏览器的渲染过程, 到底在说什么, 是在说整个流程, 输入资源, 输出页面.
步骤大体上可以这么描述

   输入html -> 解析   
                  -> 合并成 render tree -> layout -> paint ->结束.
   输入css  -> 解析 

layout: 就是安排 render tree 上面的每一个节点的位置, 大小
paint: 就是绘制每一个节点.

流程是这样, 那还有啥问题.

(1) 下载和解析是不是同步的, 不是, 是边下载边解析, 不需要等到所有的资源都下载结束才解析
也就是说: 来了 html 就解析html, 来了 css 就解析 css

(2) 在渲染的过程中, 如果遇见 js 怎么办? 是继续渲染还是停下, 先执行 js?
其实就两个答案, 要么继续, 要么停下来.

继续的话, 就是说让 js 在我渲染之后再执行, 别着急, 好的, 渲染结束之后, js 里面唰的一下执行一下:

document.write("");

这意味着, 我所有的渲染的努力都白费了.
与此相比, 在渲染的时候遇见 js 等一下, 等它执行结束, 再继续执行, 这样防止全盘努力白费,
风险小点, 所以还是等吧.

所以在渲染的过程中, 如果遇见 js, 那么就停下来, 执行它.

那能不能让 js 告诉我它到底有没有就是说, 更改 DOM, 有时候它的确不会啊, 这个时候我就白等了.
所以有 defer 和 async

这个就相当于说,
defer, defer啊, 告诉你, 你不用等我, 你继续渲染, 我不会改你的, ok
这个时候, js 就会在浏览器渲染之后再执行.

async 呢?
这个就坑爹了, 这个说, 你别等我, 我也不等你, 我反正下下来之后就执行

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83960.html

相关文章

  • 假如我是面试官,我会这样虐你

    摘要:又是金三银四的时候,我希望这份面试题能够祝你一臂之力自我和项目相关自我介绍你觉得自己的优点是你觉得自己有啥缺点你有哪些你为什么要离开上家公司你上家公司在,我们公司在,离这么远为什么要选择我们这里上家公司的同事和领导是怎么评价你的介绍下你的上 又是金三银四的时候,我希望这份面试题能够祝你一臂之力! 自我和项目相关 1、自我介绍 2、你觉得自己的优点是?你觉得自己有啥缺点? 3、你有哪些 ...

    Benedict Evans 评论0 收藏0
  • 2019 Android 高级面试题总结

    摘要:子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此的循环并不会对性能有过多的消耗。 说下你所知道的设计模式与使用场景 a.建造者模式: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 使用场景比如最常见的AlertDialog,拿我们开发过程中举例,比如Camera...

    YorkChen 评论0 收藏0
  • 2019 Android 高级面试题总结

    摘要:子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此的循环并不会对性能有过多的消耗。 说下你所知道的设计模式与使用场景 a.建造者模式: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 使用场景比如最常见的AlertDialog,拿我们开发过程中举例,比如Camera...

    wums 评论0 收藏0
  • 关于算法动态规划的实现优化

    摘要:首先说下算法对于前端的作用和应用作用不用说了提高效率和性能应用目前也是买了算法导论这本书,看得头晕,各种数学知识需要返回去重新认识,哎,终于知道了以前学的东西总有用的。。。 首先说下算法对于前端的作用和应用 作用:不用说了提高效率和性能 应用:目前也是买了算法导论这本书,看得头晕,各种数学知识需要返回去重新认识,哎,终于知道了以前学的东西总有用的。。。,自己买的哭着也要读完,不扯了,直...

    qpal 评论0 收藏0
  • 关于算法动态规划的实现优化

    摘要:首先说下算法对于前端的作用和应用作用不用说了提高效率和性能应用目前也是买了算法导论这本书,看得头晕,各种数学知识需要返回去重新认识,哎,终于知道了以前学的东西总有用的。。。 首先说下算法对于前端的作用和应用 作用:不用说了提高效率和性能 应用:目前也是买了算法导论这本书,看得头晕,各种数学知识需要返回去重新认识,哎,终于知道了以前学的东西总有用的。。。,自己买的哭着也要读完,不扯了,直...

    mykurisu 评论0 收藏0

发表评论

0条评论

王伟廷

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<