美文网首页工作生活
性能优化总结

性能优化总结

作者: _小海绵 | 来源:发表于2019-07-08 18:45 被阅读0次

    资源的合并与压缩

    • 核心:减少http请求数量(合并)减少资源请求大小(压缩)
    • html压缩:压缩这些在文本文件中有意义,但是在html中不显示的字符,包括空格,制表符,换行符等,还有一些其他意义的字符,如注释等也可以被压缩。
      1. 使用在线网站进行压缩(现在不常用)
      2. nodejs提供的 html-minifier 工具(可选是否压缩注释,是否压缩空格等)
      3. 后端模版引擎渲染压缩
    • css压缩(无效代码删除,css语义合并)
      1. 使用在线网站进行压缩
      2. 使用的 html-minifier 对 html 中对 css 压缩
      3. 使用 clean-css 对 css 压缩
    • js压缩与混乱(无效字符的删除,剔除注释,代码语义的缩减和优化,代码保护)
      1. 使用在线网站进行压缩
      2. 使用的 html-minifier 对 html 中对 js 压缩
      3. 使用 uglifyjs2 对 js 压缩
    • 文件合并
      1. 不合并时
        1. 文件与文件之间有插入的上行请求,增加了N-1个网络延迟。
        2. 受丢包问题影响严重。
        3. keep-alive经过代理服务器时可能会被打断。
      2. 合并时
        1. 首屏渲染问题。
        2. 缓存失效问题。
        3. 结局方案:
          1. 公共库单独合并与业务代码分开。
          2. 不同页面分别打包(异步加载组件)
          3. 见机行事,随机应变
      3. 如何进行文件合并?
        1. 使用在线网站进行文件合并
        2. 使用nodejs实现文件合并(gulp webpack fis3)

    图片相关优化

    • 各图片格式对比:
      1. jpg: 有损压缩 压缩率高 体积小 加载快 不支持透明(大部分不需要透明图片的业务场景比如大的背景图或轮播图等)
      2. png: 无损压缩 体积大 质量高 浏览器兼容好 (颜色简单,需要透明图片,对比性强的小图片)
        1. png8 -> 256色 支持透明
        2. png24 -> 2^24色 不支持透明
        3. png32 -> 2^24色 支持透明
      3. webp 由谷歌2010提出 压缩格式更好 在ios webview内有兼容问题,安卓没问题;优势在于它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式,Alpha透明以及动画的特性,在JPEG和PNG上的转换效果都非常优秀稳定和统一。
      4. SVG(可缩放矢量图形)文本文件内嵌在代码中,体积更小 可以无限放大不失真 兼容性好 图片样式相对简单(例:iconfont)
      5. Base64
        1. 文本文件 依赖代码 小图片的最优解决方案 作为雪碧图的补充而存在
        2. Base64是一种用于传输8Bit字节码的编码形式,将图片通过Base64编译,可将编码结果直接写入html或css从而减少HTTP的请求。
        3. 使用条件:1. 图片的实际尺寸小,更新频率低无法以雪碧图等形式与其他小图融合。
    • css雪碧图:优:通过图片整合减少HTTP请求;缺:整合图片过大时,一次加载过慢或请求失败时,会导致页面失常(可以根据业务场景拆分整合为多张雪碧图,移动端使用较少)。

    CSS JS的加载与执行

    1. 一个网站在浏览器端是如何被渲染的?


      页面加载渲染过程.png
    2. HTML渲染过程特点:

      1. 顺序执行(自上而下) 并发加载(浏览器对域名的加载数量有限制)
      2. 是否阻塞
        1. CSS阻塞
          1. CSS在head中以link形式引入会阻塞页面的渲染,需等link标签所引入的CSS加载后,方进行渲染。
          2. CSS会阻塞JS的执行(JS执行可能会依赖已经生成好CSS的DOM)。
          3. CSS不阻塞外部脚本加载。
          4. CSS加载方式
            1. link 2. @import 3. 行内样式 4. 内部样式表
          5. link与@import的区别:
            1. link功能更多,可以定义RSS,Rel等,@import只能加载CSS。
            2. 解析link时,页面会同步加载css。@import所引用的只能等页面加载完成后加载。
            3. @import需要IE5以上
            4. link可以JS引入。@import不可
          6. CSS选择器优先级
            1. !important > 行内 > id > class >tag > * > 继承 > 默认
            2. 从右向左解析
            3. 约具体优先级越高,后面的会覆盖前面的
          7. CSS书写顺序:位置属性 > 大小 > 文字系列 > 背景边框 > 其他
        2. JS阻塞
          1. <script>直接引入会阻塞页面的渲染(JS执行可能会改变现有页面结构)。
          2. JS不会阻塞资源的加载。
          3. JS顺序执行,阻塞后续JS逻辑的执行。
          4. defer属性:
            1. 延迟脚本执行,DOM加载完成后再执行脚本。
            2. 非外部引入的内置<script>标签defer属性不生效,也不应该在外部脚本中使用document.write
          5. async属性:
            1. 使用另一个进程下载脚本,下载时不会阻塞渲染,脚本下载完毕后暂停解析HTML,执行该脚本,脚本执行完毕后恢复解析HTML。
            2. 当同时多个外部脚本加载时,无法保障执行顺序,哪个先下载完成就先执行哪个。
          6. 脚本直接无依赖关系就使用async,反之用defer。
          7. 同时使用async与defer时,defer不起作用,由async决定。
      3. 依赖关系
      4. 引入方式

    懒加载与预加载

    1. 懒加载:

      1. 图片进入可视区域之后请求图片资源。
      2. 适用于电商等图片很多,页面很长的业务场景。
      3. 可以有效的减少无效资源的加载。
      4. 并发记载的资源过多会阻塞js加载,影响网站的正常使用。
      /**HTML部分**/
      <img src="" class="image-item" lazyload="true" data-original="图片路径"/>
      /**JS部分**/
      //获取可是区域的高度
      var viewHeight = document.documentElement.clientHeight;
      function lazyload() {
          var eles = document.querySelectorAll('img[data-original][lazyload]')
          Array.prototype.forEach.call(eles, function (item, index) {
              var rect;
              if (item.dataset.original === '') {
                return
              }
              //getBoundingClientRect:返回元素的大小及其相对于视口的位置。
              rect = item.getBoundingClientRect()
              if (rect.bottom >= 0 && rect.top < viewHeight) {
                !function () {
                  var img = new Image()
                  img.src = item.dataset.url
                  img.onload = function () {
                    item.src = img.src
                  }
                  item.removeAttribute("data-original")
                  item.removeAttribute("lazyload")
                }()
              }
          }
      }
      //手动调用,使第一屏图片正常显示
      lazyload()
      document.addEventListener('scroll', lazyload)
      //需要预先设置图片高度占位,如果图片没有预设高度,每个img的hight几乎为零,会导致首屏可是区域图片过多。
      
    2. 预加载

      1. 图片等静态资源在使用之前的提前请求。
      2. 资源被需要时可以从缓存中加载,提升用户体验。
      3. 页面展示的依赖关系维护。
      //解决方案1:使用Image对象
          var image = new Image()
          image.src = "图片地址"
      //解决方案2:使用XMLHttpRequest对象
          //优:对整个请求过程有更好的监控,可以更好的控制传输过程。
          //缺:存在跨域问题
      //解决方案3:使用preload.js
      
      

    重绘与回流

    • 页面渲染方式:
      1. 服务器渲染(所见即所得-页面呈现的内容我们在html源文件可以找到)
      2. 客户端渲染(页面呈现的内容,在html源文件找不到)
    • 浏览器内核:1. 渲染引擎(HTML解释器,CSS解释器,布局,网络,存储等) 2. JS引擎
    • 浏览器渲染
      1. HTML解释器(将HTML文档经过语法分析输出DOM树)
      2. CSS解释器 (解析CSS文档 生成样式规则)
      3. 图布局层计算模式(布局计算每个对象的精确位置与大小)
      4. 视图绘制模式(进行具体节点的图像绘制,将像素渲染在屏幕上)
      5. JavaScript引擎(编译执行JavaScript代码)
    • 回流: 当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建,这就称为回流(reflow),当页面 布局 和 几何属性 改变时就需要回流。
      1. 触发页面重新布局的属性
        1. 盒子模型相关属性(width,height, padding, margin, display, border-width,border, min-height )
        2. 定位属性及浮动(top, bottom, left, right, position, float, clear)
        3. 改变节点内部文字结构(text-align, overflow-y, font-weight, overflow, font-family, line-height, vertival-align, white-space, font-size)
    • 重绘 :当render tree中的一些元素需要更新属性,而这些属性只影响元素的外观,风格,而不影响布局的,称之为重绘(background-color,color)
    • ==回流必定引起重绘,重绘不一定会引起回流==
    • 新建DOM的过程
      1. 获取DOM后分割为多个图层
      2. 对每个涂层对节点计算样式结果
      3. 为每个节点生成图形和位置(Layout-回流和重新布局)
      4. 将每个节点绘制填充到图层位图中
      5. 将图层作为纹理上传到CPU
      6. 复合多个图层到页面上生成最终屏幕图像
    • 将 频繁重绘回流++ 的DOM元素单独作为一个 独立图层,那么这个DOM元素的重绘和回流的影响 只会在这个图层中。
    • 生成新图层
      1. 3D或者透视变化CSS属性(translated 3d,translateZ)
      2. 使用加速视频解码的video标签,iframe标签
      3. 拥有3D(WebGL)上下文或者加速的2D上下文<canvas>
      4. 混合插件(flash)
      5. 使用动画的元素(opacity)
      6. 元素有一个包含符合层的后代节点
      7. 该元素在符合层上渲染,z-index较低,有兄弟节点
    • 优化点:
      1. 用 translate 代替 top。
      2. 用 opacity 替换 visibility,使用visibility替换display:none。
      3. 不要一条一条修改DOM的样式,预先定义好class,然后修改DOM的className。
      4. DOM离线后修改(先display:none,修改完成后再显示)。
      5. 不要把DOM节点的属性值(offsetHeight,offsetWidth)放在循环里当循环的变量。
      6. 不使用table。
      7. 动画实现速度的选择,速度越快回流次数越多。
      8. 将频繁运行的动画变为图层,图层可以阻止节点回流影响别的元素。
      9. 启用GPU加速

    浏览器存储

    • Cookie:(HTTP请求无状态,所以需要cookie去维持客户端状态)
      1. 生成方式:
        1. http response header 中的 set-cookie。
        2. js中document.cookie 可以读写cookie。
      2. 服务端生成,客户端存储与管理,存储上限4KB。
      3. 以域名的形式进行区分,不同域名下的cookie是独立的。可以设置生效的域,可以操作Cookie是当前域及当前域下的所有子域,一个域名上限20条。
      4. 使用场景:
        1. 会话状态管理,(登录状态,购物车)
        2. 个性化设置(自定义设置,主题)
        3. 浏览器行为跟踪
        4. 浏览器端和服务器端交互。
        5. 客户端自身数据存储。
      5. 属性:1. expire 过期时间 2. httponly禁止JS读写
      6. Cookie在相关域名下存在CDN的流量损耗(解决办法:CDN的域名和主站域名分开)
    • LocalStorage(专职浏览器存储;5M左右; 仅在客户端使用,不与服务端通信; 接口封装较好; 浏览器本地缓存方案)
    • SessionStorage(会话级别的浏览器存储;5M左右; 仅在客户端使用,不与服务端通信; 接口封装较好; 对于表单信息的维护)
    • IndexedDB(是一种低级API,用于客户端存储大量结构化数据,该API使用索引来实现对该数据的高性能搜索,虽然WebStorage对于存储较少量的数据很有用,但对于存储更大量的数据化结构来说,这个方法不太有用,IndexedDB提供了一个解决方案。可以为应用创建离线版本)
    • PWA(Web App新模型,渐进式Web App,通过一系列新的Web特性,配合优秀的UI交互设计,逐步的增强Web App的用户体验)
      1. 可靠性:在没有网络的环境下也能提供基本的页面访问,为不会出现“未链接到互联网”的页面。
      2. 快速:针对网络渲染和网络数据访问有较好优化。
      3. 融入:应用可以被增加到手机桌面,并且和普通应用一样有全屏,推送等特性。
      4. 性能检测-lighthouse 谷歌插件
    • Service Worker:一个脚本,浏览器独立于当前页面,将其在后台运行,为实现一些不依赖页面或者用户交互的特性打开了一扇大门。在未来这些特性将包括推送信息,背景后台同步,geofencing(地理围栏定位),但它将推出的第一个首要特性,就是拦截和处理网络请求的能力,包括以编程方式来管理被缓存的响应。

    浏览器缓存

    • httpheader中的Cache-Control(Response,Request)

      1. max-age:最大缓存时间
        1. 在HTTP1.1被提出;
        2. max-age:31536000;
        3. status Code:200;
        4. 在这段时间内浏览器不会再向服务器发送请求。
      2. s-maxage:最大缓存时间
        1. status Code:304;
        2. 只对public缓存设备(CDN)生效;
        3. 同时出现时优先级高于max-age,若s-maxage未过期则向代理服务器请求缓存资源;
        4. s-maxage:31536000;
      3. private:只能被浏览器缓存(默认)
      4. public:可以被代理服务器与浏览器缓存(未明确设置public 但使用了s-maxage也表示可以被代理服务器缓存)
      5. no-cache:绕开浏览器,每次请求不会询问浏览器缓存直接与服务器通信确认资源是否过期(Cache-Control:private,max-age=0,no-cache)
      6. no-store:不使用任何缓存策略。
    • Expires:(HTTP1.0版本有效)缓存过期时间;用来指定资源的到期时间,是服务器端的具体时间点,告诉浏览器在过期时间之前可以直接从浏览器缓存取数据,无需再次请求。

      1. expires:Wed, 24 Jun 2018 12:19:34 GMT
      2. 优先级:Cache-Control > Expires 同时存在以Cache-Control为准
      3. 会存在时间戳问题,此属性对本地时间有依赖,若修改客户端时间会失效。
    • Last-Modified/If-Modified-Since(基于客户端和服务端协商的缓存机制)

      1. If-Modified-Since 资源文件的最后的修改时间:在request header上 ;若资源没有更新,status Code:304;
      2. Last-Modified 资源最后修改时间:存在response header中
      3. 与Cache-Control配合使用。
      4. Last-Modified缺点:
        1. 某些服务器不能获取精确的修改时间。
        2. 有可能文件的修改时间改了,但是文件内容没有更改。
    • Etag/If-None-Match(文件内容的hash值)

      1. Etag存在response header中
      2. If-None-Match存在request header中
      3. 两者相比较有变化status Code:200,没变化status Code:304
      4. 比Last-Modified/If-Modified-Since更精确,优先级更高。
      5. 与Cache-Control配合使用。
    • 分级缓存策略

      1. 200状态(form cache):由expires/cache-control控制控制。1. expires绝对时间,cache-control相对时间,两者存在时cache-control覆盖expires,只要没有失效,浏览器只访问自己的缓存。
      2. 304状态:由Last-Modified/Etag控制,协商缓存情况。
      3. 200状态:没有缓存或者协议缓存失效,浏览器直接去服务器下载更新数据
    • 缓存流程图


      缓存过程.png
    • Cache-control流程图


      cache-control.png

    服务端性能优化

    • VUE渲染面临的问题-首屏渲染
      1. 构建层模版编译。
      2. 对无关数据进行prerender
      3. 服务端渲染

    相关文章

      网友评论

        本文标题:性能优化总结

        本文链接:https://www.haomeiwen.com/subject/ajfxhctx.html