1 Star 2 Fork 0

神奇码农 / WebInterview

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
性能优化.md 14.89 KB
一键复制 编辑 原始数据 按行查看 历史
unknown 提交于 2021-03-05 20:08 . 拆分

性能优化

1.性能优化的几个方面?

1.资源压缩合并,减少HTTP请求

2.非核心代码异步加载

3.利用浏览器缓存

4.使用CDN

5.预解析DNS

2.如何进行首屏优化

1》首先对于首屏,我认为用户体验有三个阶段:

①就是页面第一个东西加载出来:用户会感觉到自己已经成功访问到这个网址了

②页面第一个含有有用信息的东西加载出来:用户会觉得能在这个网站上获取到有用的信息

③页面可以进行交互:用户进行交互体验

2》然后对前面所学的性能优化进行一下总结即可

3.什么情况会造成内存泄漏?

避免意外的全局变量的产生(非严格模式) 称为全局变量后 就不会在函数执行完被回收掉了

避免反复运行形成大量的闭包

避免脱离的DOM元素

4.异步加载?

  • 动态脚本加载
  • defer
  • async

5.加载方式区别?

  • defer是在html解析完毕才执行,如果有多个则按加载顺序执行
  • async是加载完毕后立即执行,如果是多个,执行顺序与加载顺序无关

6.浏览器缓存?

分类

强缓存

是指在时间之内不会询问服务器是否需要缓存。

Expires(过期时间) Expries:Sun Jun 16 2019 23:55:21 GMT(服务器时间)

Cache-Control(相对时间)

协商缓存

如果本地有缓存,则需要向服务器询问是否需要使用本地缓存。

Last-Modified if-Modified-Since

Etag If-None-Matc

7.预加载?

在开发中,可能会遇到这样的情况。有些资源不需要马上用到,但是希望尽早获取,这时候就可以使用预加载。

预加载其实是声明式的 fetch ,强制浏览器请求资源,并且不会阻塞 onload 事件,可以使用以下代码开启预加载

<link rel="preload" href="http://example.com">

预加载可以一定程度上降低首屏的加载时间,因为可以将一些不影响首屏但重要的文件延后加载,唯一缺点就是兼容性不好。

8.预渲染?

可以通过预渲染将下载的文件预先在后台渲染,可以使用以下代码开启预渲染

<link rel="prerender" href="http://example.com"> 

预渲染虽然可以提高页面的加载速度,但是要确保该页面大概率会被用户在之后打开,否则就是白白浪费资源去渲染。

9.CDN?

CDN 的原理是尽可能的在各个地方分布机房缓存数据,这样即使我们的根服务器远在国外,在国内的用户也可以通过国内的机房迅速加载资源。

因此,我们可以将静态资源尽量使用 CDN 加载,由于浏览器对于单个域名有并发请求上限,可以考虑使用多个 CDN 域名。并且对于 CDN 加载静态资源需要注意 CDN 域名要与主站不同,否则每次请求都会带上主站的 Cookie,平白消耗流量。

10.DNS 预解析?

DNS 解析也是需要时间的,可以通过预解析的方式来预先获得域名所对应的 IP。

<meta http-equiv='x-dns-prefetch-control' content='on'>
<link rel="dns-prefetch" href="//yuchengkai.cn">

在https协议中默认a标签不会开启预解析,因此需要手动设置meta

11.节流?

考虑一个场景,滚动事件中会发起网络请求,但是我们并不希望用户在滚动过程中一直发起请求,而是隔一段时间发起一次,对于这种情况我们就可以使用节流。

理解了节流的用途,我们就来实现下这个函数

// func是用户传入需要防抖的函数
// wait是等待时间
const throttle = (func, wait = 50) => {
  // 上一次执行该函数的时间
  let lastTime = 0
  return function(...args) {
    // 当前时间
    let now = +new Date()
    // 将当前时间和上一次执行函数时间对比
    // 如果差值大于设置的等待时间就执行函数
    if (now - lastTime > wait) {
      lastTime = now
      func.apply(this, args)
    }
  }
}

setInterval(
  throttle(() => {
    console.log(1)
  }, 500),
  1
)

12.防抖?

考虑一个场景,有一个按钮点击会触发网络请求,但是我们并不希望每次点击都发起网络请求,而是当用户点击按钮一段时间后没有再次点击的情况才去发起网络请求,对于这种情况我们就可以使用防抖。

理解了防抖的用途,我们就来实现下这个函数

// func是用户传入需要防抖的函数
// wait是等待时间
const debounce = (func, wait = 50) => {
  // 缓存一个定时器id
  let timer = 0
  // 这里返回的函数是每次用户实际调用的防抖函数
  // 如果已经设定过定时器了就清空上一次的定时器
  // 开始一个新的定时器,延迟执行用户传入的方法
  return function(...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      func.apply(this, args)
    }, wait)
  }
}

13.懒执行?

懒执行就是将某些逻辑延迟到使用时再计算。该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏就使用的,就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒。

14.懒加载?

懒加载就是将不关键的资源延后加载。

懒加载的原理就是只加载自定义区域(通常是可视区域,但也可以是即将进入可视区域)内需要加载的东西。对于图片来说,先设置图片标签的 src 属性为一张占位图,将真实的图片资源放入一个自定义属性中,当进入自定义区域时,就将自定义属性替换为 src 属性,这样图片就会去下载资源,实现了图片懒加载。

懒加载不仅可以用于图片,也可以使用在别的资源上。比如进入可视区域才开始播放视频等等。

15.图片优化?

计算图片大小 对于一张 100 * 100 像素的图片来说,图像上有 10000 个像素点,如果每个像素的值是 RGBA 存储的话,那么也就是说每个像素有 4 个通道,每个通道 1 个字节(8 位 = 1个字节),所以该图片大小大概为 39KB(10000 * 1 * 4 / 1024)。

但是在实际项目中,一张图片可能并不需要使用那么多颜色去显示,我们可以通过减少每个像素的调色板来相应缩小图片的大小。

了解了如何计算图片大小的知识,那么对于如何优化图片,想必大家已经有 2 个思路了:

  • 减少像素点
  • 减少每个像素点能够显示的颜色

16.图片加载优化?

1.不用图片。很多时候会使用到很多修饰类图片,其实这类修饰图片完全可以用 CSS 去代替。

2.对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用 CDN 加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片。2。 对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用 CDN 加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片。 3.小图使用 base64 格式

4.将多个图标文件整合到一张图片中(雪碧图)

5.选择正确的图片格式:

1.对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式。因为 WebP 格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好

2.小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替

3.照片使用 JPEG

17.js css 顺序对前端优化影响?

上面我们说到了整个渲染流程,但是没有说到 css 和 js 对渲染的影响。渲染树的构成必须要 DOM 树和 CSSOM 树的,所以尽快的构建 CSSOM 树是一个重要的优化手段,如果 css 文件放在尾部,那么整个过程就是一个串行的过程先解析了 dom,再去解析 css。所以 css 我们一般都是放在头部,这样 DOM 树和 CSSOM 树的构建是同步进行的。

再来看 js,因为 js 的运行会阻止 DOM 树的渲染的,所以一旦我们的 js 放在了头部,而且也没有异步加载这些操作的话,js 一旦一直在运行,DOM 树就一直构建不出来,那么页面就会一直出现白屏界面,所以一般我们会把 js 文件放在尾部。当然放到尾部也不是就没有问题了,只是问题相对较小,放到尾部的 js 文件如果过大,运行时间长,代码加载时,就会有大量耗时的操作造成页面不可点击,这就是另一个问题,但这肯定比白屏要好,白屏是什么页面都没有,这种是页面有了只是操作不流畅。

js 脚本放在尾部还有一个原因,有时候 js 代码会有操作 dom 节点的情况,如果放在头部执行,DOM树还没有构建,拿不到 DOM 节点但是你又去使用就会出现报错情况,错误没处理好的话页面会直接崩掉

18.重排重绘为什么会影响渲染,如何避免?

重排和重绘为什么会影响渲染,哪个影响更大,如何避免是经常被问到的一道题目,我们先来说一下重绘

  • 重绘

重绘指的是不影响界面布局的操作,比如更改颜色,那么根据上面的渲染讲解我们知道,重绘之后我们只需要在重复进行一下样式计算,就可以直接渲染了,对浏览器渲染的影响相对较小

  • 重排

重排指的是影响界面布局的操作,比如改变宽高,隐藏节点等。对于重排就不是一个重新计算样式那么简单了,因为改变了布局,根据上面的渲染流程来看涉及到的阶段有样式计算,布局树重新生成,分层树重新生成,所以重排对浏览器的渲染影响是比较高的

  • 避免方法

1.js 尽量减少对样式的操作,能用 css 完成的就用 css

2.对 dom 操作尽量少,能用 createDocumentFragment 的地方尽量用

3.如果必须要用 js 操作样式,能合并尽量合并不要分多次操作

4.resize 事件 最好加上防抖,能尽量少触发就少触发

5.加载图片的时候,提前写好宽高

19.何时缓存在memory,合适缓存在dist?

这个问题网上很少找的到标准答案,大家一致的说法是js,图片文件浏览器会自动保存在memory中,css文件因为不常修改保存在dist里面,我们可以打开掘金网站,很大一部分文件都是按照这个规则来的,但是也有少数js文件也是缓存在dist里面。所以他的存放机制到底是什么样了?我带着这个疑问查了好多文章,虽然最后没有确切找到答案,但是一个知乎的回答可以给我们提供思路,下面引用一个知乎回答者一段话

  • 第一个现象(以图片为例):访问-> 200 -> 退出浏览器再进来-> 200(from disk cache) -> 刷新 -> 200(from memory cache)。总结: 会不会是chrome很聪明的判断既然已经从disk拿来了, 第二次就内存拿吧 快。(笑哭)
  • 第二个现象(以图片为例):只要图片是base64 我看都是from memroy cache。总结: 解析渲染图片这么费劲的事情,还是做一次然后放到内存吧。用的时候直接拿
  • 第三个现象(以js css为例):个人在做静态测试的发现,大型的js css文件都是直接disk cache。结: chrome会不会说 我去 你这么大太占地方了。你就去硬盘里呆着吧。慢就慢点吧。
  • 第四个现象:隐私模式下,几乎都是 from memroy cache。总结: 隐私模式 是吧。我不能暴露你东西,还是放到内存吧。你关,我死。

上面几点是虽然很幽默,但是却可以从中找到一部分答案,但是我觉得另一个知乎回答我更赞同

浏览器运行的时候也是由几个进程协作的,所以操作系统为了节省内存,会把一部分内存里的资源交换回磁盘的交换区,当然交换是有策略的,比如最常用的就是LRU。

什么时候存dist,什么时候存memoey都是在浏览器控制下的,memory不够了可能就会考虑去存dist了,所以经过上面所说我自己总结结果如下

  • 大一点的文件会缓存在dist里面,因为内存也是有限的,磁盘的空间更大
  • 小一点文件js,图片存的是memory
  • css文件一般存在dist
  • 特殊情况memory大小是有限制的,浏览器也会根据自己的内置算法,把一部分js文件存到dist里面

20.CSS选择符优化

在大多数人的观念中,都觉得浏览器对 CSS选择符的解析式从左往右进行的,例如 #toc A { color: #444; }这样一个选择符,如果是从右往左解析则效率会很高,因为第一个 ID选择基本上就把查找的范围限定了,但实际上浏览器对选择符的解析是从右往左进行的。如上面的选择符,浏览器必须遍历查找每一个 A标签的祖先节点,效率并不像之前想象的那样高。根据浏览器的这一行为特点,在写选择符的时候需要注意很多事项,有兴趣的童鞋可以去了解一下。

CDN加速

CDN(contentdistribute network,内容分发网络)的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳,如下图。

由于CDN部署在网络运营商的机房,这些运营商又是终端用户的网络服务提供商,因此用户请求路由的第一跳就到达了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力。 CDN缓存的一般是静态资源,如图片、文件、CSS、script脚本、静态网页等,但是这些文件访问频度很高,将其缓存在CDN可极大改善网页的打开速度。

反向代理

传统代理服务器位于浏览器一侧,代理浏览器将http请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站web服务器接收http请求。

参考链接

https://blog.csdn.net/qianyu6200430/article/details/109712717

https://blog.csdn.net/qq_37674616/article/details/86490686

https://www.cnblogs.com/liubingyjui/p/10095633.html

1
https://gitee.com/WebInterviewHub/WebInterview.git
git@gitee.com:WebInterviewHub/WebInterview.git
WebInterviewHub
WebInterview
WebInterview
master

搜索帮助