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

性能优化总结

作者: _小海绵 | 来源:发表于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. 服务端渲染

相关文章

  • iOS 性能优化总结

    iOS 性能优化总结 iOS 性能优化总结

  • IOS的性能优化包括哪几点

    iOS性能优化总结 iOS性能优化总结。关于 iOS 性能优化梳理: 基本工具、业务优化、内存优化、卡顿优化、布局...

  • App瘦身、性能优化总结

    App瘦身、性能优化总结 App瘦身、性能优化总结

  • Awesome Extra

    性能优化 性能优化模式 常见性能优化策略的总结 Spark 性能优化指南——基础篇 Spark 性能优化指南——高...

  • iOS必读 - 收藏集 - 掘金

    iOS 性能优化总结 - iOS - 掘金关于iOS 性能优化梳理: 基本工具、业务优化、内存优化、卡顿优化、布局...

  • Android 性能优化

    Android APP性能优化(最新总结)Android性能优化全方面解析Android性能优化的方方面面http...

  • 17.MySQL优化

    《高性能MySQL》——这本书都有的 “字段”优化总结 “索引”优化总结 索引的优化 “查询SQL”优化总结 “引...

  • mysql程序

    MySQL性能优化方案总结

  • 前端性能优化

    js性能小贴士——优化循环 前端网页与js性能优化 我总结的js性能优化的小知识 提高 web 应用性能之 Jav...

  • 前端性能 优化 大全

    js性能小贴士——优化循环 前端网页与js性能优化 我总结的js性能优化的小知识 提高 web 应用性能之 Jav...

网友评论

    本文标题:性能优化总结

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