前端性能优化

资源的合并与压缩

  • 核心
    • 减少http请求数量
    • 减少请求资源大小
  • html压缩
    • 在HTML中不显示的字符,包括空格、制表符、换行符等,还有一些其他意义的字符,如HTML注释也可以被压缩
    • 压缩方法
      • 使用在线网站进行压缩
      • nodejs提供了html-minifier工具(构建时进行压缩)
      • 后端模板引擎渲染压缩
  • css压缩
    • 无效代码删除(无意义字符)
    • css语义合并(语义重复,需要进行合并)
    • 压缩方法
      • 使用在线网站进行压缩
      • html中css使用html-minifier对html进行压缩
      • 使用clean-css对css进行压缩
  • JS压缩与混乱
    • 无效字符的删除
    • 剔除注释
    • 代码语义的缩减和优化
    • 代码保护
    • 压缩和混乱方法
      • 使用在线网站进行压缩
      • 使用html-minifier对html中的js进行压缩
      • 使用uglifyjs2对js进行压缩
  • 文件合并
    • 文件合并存在的问题
      • 首屏渲染问题
      • 缓存失效问题
    • 合并方法
      • 使用在线网站进行文件合并
      • 使用nodejs实现文件合并

图片相关优化

  • png8/png24/png32之间的区别
    • png8: 256色+支持透明
    • png24: 224色+不支持透明
    • png32: 224色+支持透明
    • 每种图片格式都有自己的特定,根据不同的业务场景选择不同的图片格式很重要
  • 不同格式图片常用的业务场景
    • jpg有损压缩,压缩率高,不支持透明(应用于大部分不需要透明图片的业务场景)
    • png支持透明,浏览器兼容好(应用于大部分需要透明图片的业务场景)
    • webp压缩程度更好,在ios webview有兼容性问题(应用于安卓全部)
    • svg矢量图,代码内嵌,相对较小,图片样式相对简单的场景(应用于图片样式相对简单的业务场景,如iconfont)
  • 图片压缩:针对真实图片情况,舍弃一些相对无关紧要的色彩信息
    • css雪碧图:把用到的一些图片整合到一张图片中
    • Image inline:将图片的内容内嵌到html当中(base64)
      • 优点: 减少网站http请求数量
    • 使用矢量图:使用svg进行矢量图的绘制;使用iconfont解决icon问题
    • 在安卓下使用webp:具有更优的图像数据压缩算法,带来更小的图片体积,拥有肉眼识别无差异的图片质量;具备无损和有损的压缩模式、alpha透明以及动画的特性,在jpeg和png的转化效果都非常优秀、稳定和统一
    • 图片在线压缩网站/智图

css和js加载与执行

  • 一个网站在浏览器端是如何进行渲染的


    • html通过网址请求回来,由字节流转换为字符流
    • 浏览器进行词法分析,将html文档从上到下依次转换为词法token并添加到DOM树中
    • script/link标签中的外部资源浏览器进行请求
    • 浏览器V8执行引擎来执行
    • css资源解析为CSSOM
    • CSSOM+DOM TREE形成渲染树,再进行绘制
  • HTML渲染过程特点

    • 顺序执行、并发加载
      • 词法分析对html标签从上到下依次解析
      • 并发加载:HTML中外部资源并发请求
      • 并发上限:对某个域名下并发请求的数量是有限制的,因此需要托管到多个cdn
    • 是否阻塞
    • 依赖关系
    • 引入方式
  • css阻塞

    • css head中阻塞页面的渲染(css通过link方式在head中引用,加载完再进行渲染)
    • css不阻塞资源的的加载
    • css阻塞js执行(因为js执行可能依赖css的样式)
  • js阻塞

    • 直接引入的js(不用defer/async)阻塞页面的渲染
    • js不阻塞资源的加载
    • js顺序执行,阻塞后续js逻辑的执行

懒加载与预加载

  • 懒加载
    • 图片进入可视区域之后请求图片资源
    • 对于电商等图片很多、页面很长的业务场景适用
    • 减少无效资源的加载
    • 并发加载的资源过多会阻塞js的加载,影响网站的正常使用
  • 预加载
    • 图片等静态资源在使用之前的提前请求
    • 资源使用到时能从缓存中加载,提升用户体验
    • 页面展示的依赖关系维护
  • 懒加载和预加载使用场景
    • 懒加载:电商网站图片很多,进入可视区域再加载图片
      • 把图片的src置为空
      • 图片的data-image属性存放图片真正地址
      • 监听scroll事件,在scroll的回调中判断图片是否进入进入可视区(可视区高度clientHeight,图片当前位置通过getBoundingClientRect()来获取),如果在可视区,将data-image的值放入src中
    • 预加载:抽奖页面图片的选中态和非选中态是两张图片,将两种图片预加载,需要时从缓存中加载;还有活动页是很多图片组成的动画,将所有动画帧加载完再进行播放
      • 方法一:通过标签加载,并设置display:none,在需要时修改display
      • 方法二:使用Image对象,new一个image对象,并且src为所需要预加载的资源
      • 方法三:通过XMLHttpRequest对象。open所需的资源,再send,在callback中处理
      • 方法四:使用preLoad库

重绘与重排

  • 原理

    • 浏览器一个线程=》Javascript解析,一个线程=》UI渲染,这两个线程是互斥的
    • 频繁触发重绘与重排,会导致UI频繁渲染,阻塞JS
  • 重排

    • 当render tree中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就称为重排(reflow)
    • 当页面布局和几何属性改变时就需要重排
  • 重绘

    • 当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不影响布局的,比如background-color,就称为重绘(repaint)
    • 重排必定引起重绘,重绘未必引发重排
  • 避免重绘重排的方法

    • 触发页面布局的属性
      • 盒子模型相关属性会触发重布局
      • 定位属性及浮动也会触发重布局
      • 改变节点内部文字结构也会触发重布局


    • 只触发重绘的属性


    • 方法
      • 避免使用触发重绘、重排的css属性
      • 将频繁重绘重排的DOM元素作为一个单独的图层,那么这个DOM元素的重绘和重排的影响只会在这个图层中


  • 利用Chrome的performance进行性能分析

  • 常见优化点

    • 用translate替代top/left等(translate不会触发重排 )
    • 用opacity替代visibilitiy(opacity不会触发重排重绘,visibility会触发重绘 )
    • 不要一条条修改DOM样式,预先定义好class,然后修改DOM的className
    • 把DOM离线后在修改,比如讲DOM先display:none,进行一系列操作修改后,再把它显示出来
    • 不要把DOM节点的属性值(如offsetHeight/offsetWidth)放在一个循环里当初循环里的变量
    • 不要使用table布局,可能很小的改动会造成整个table的重新布局
    • 动画实现速度的选择,动画频率过高导致频繁重排重绘,会阻塞js线程
    • 对于动画新建图层(重排重绘减小影响面,will-change:transform;transform:translateZ(0))
    • 启用GPU硬件加速

浏览器存储

  • 浏览器存储
    • cookie
      • 因为HTTP请求无状态,所以需要cookie去维持客户端状态
      • http response header中set-cookie放入浏览器cookie中(cookie由服务端生成,客户端存储)
      • js中可通过document.cookie来读写cookie
      • cookie存储的限制
        • 作为浏览器存储,大小4kb左右
        • 需要设置过期时间expire
        • cookie是域名维度下的概念,所有这个域名都会携带cookie,造成cdn的流量损耗(cdn域名和主站域名区分开,cdn存放静态文件,这样请求静态页面就不会携带cookie)
    • localStorage
      • html5设计出来专门用于浏览器存储的
      • 大小为5M左右
      • 仅在客户端使用,不和服务端进行通信
      • 接口封装较好
      • 浏览器本地缓存方案
    • sessionStorage
      • 会话级别的浏览器存储
      • 大小为5M左右
      • 仅在客户端使用,不和服务端进行通信
      • 接口封装较好
      • 浏览器本地缓存方案
    • indexedDB
      • 用于客户端存储大量结构化数据,使用索引来实现对该数据的高性能搜索
      • 为应用创建离线版本
  • PWA
    • 一种Web App新模型(Progressive Web Apps)
    • 可靠:在没有网络的环境中也能提供基本的页面访问,而不会出现“未连接到互联网”的页面
    • 快速:针对网页渲染及网络数据访问有较好优化
    • 融入:应用可以被增加到手机卓明,并且和普通应用一样有全屏、推送等特性
  • Service Worker
    • Service Worker是一个脚本,浏览器独立于当前网页,将其在后台运行,为实现一些不依赖页面或者用户交互的特性打开了一扇大门。
    • 拦截和处理网络请求,实现一个离线应用
    • 使用Serviece Worker 在后台运行同时能和页面通信的能力,去实现大规模后台数据的处理

缓存策略

  • 强缓存(浏览器端缓存策略)——服务器端改变,客户端无感知

    • cache_control
      • max-age:指定缓存最大有效时间
      • s-maxage:指定pubilc缓存设备(如cdn)缓存有效时间
      • no-cache:搭配max-age=0使用,发请求到服务端,从服务端的last-modifiy等信息来判断是否使用缓存
      • no-store:不使用任何缓存策略
    • expires
      • 缓存过期时间,用来指定资源到期的时间,是服务器端的具体时间点
      • 告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,无需再次请求
  • 协商缓存(取到服务器端最新的版本)

    • Last-Modified/If-Modified-Since(响应头/请求头)
      • 基于客户端和服务端协商的缓存机制
      • last-modified——响应头
      • if-modified-since——请求头
      • 需要与cache-control共同使用
      • 缺点
        • 某些服务端不能获取精确的修改时间
        • 文件修改时间改了,但文件内容没有变
    • Etag/If-None-Match
      • 文件内容的hash值
      • etag——响应头
      • if-none-match——请求头
      • 需要与cache-control共同使用
  • 浏览器优先走强缓存,若过期,再看协商缓存


  • chrome://cache查看缓存

  • 浏览器缓存流程图


  • cache-control参数图


服务器端性能优化

  • vue渲染有什么问题
    • 先下载vue.js
    • 执行vue.js代码
    • 生成html页面
    • 首屏性能不好
  • 没有前端框架时,用jsp/php在服务器端进行数据的填充,发送给客户端就是已经充填好数据的html
  • 优化方案
    • 构建层模板编译
    • 数据无关的prerender的方式
    • 服务器端渲染

推荐阅读更多精彩内容

  • 围绕前端的性能多如牛毛,涉及到方方面面,以我我们将围绕PC浏览器和移动端浏览器的优化策略进行罗列注意,是罗列不是展...
    流动码文阅读 387评论 0 0
  • 前端性能优化资料整理 页面性能差的直接后果是用户需要等待,而等待,尤其是不确定要多长时间的等待会给用户带来焦虑,为...
    飘零之雪阅读 213评论 2 3
  • PC浏览器前端优化策略 pc端优化的策略很多,如Slow(YSlow时Yahoo发布的一款Firefox插件,现C...
    姒沝無痕阅读 72评论 0 0
  • AJax 优化 缓存 Ajax 请求尽量使用GET, 仅取决于cookie数量 Cookie 优化 减少Cooki...
    KeKeMars阅读 7,450评论 5 86
  • 性能优化的话大致有以下几个部分:加载优化图片优化CSS优化脚本优化渲染优化 加载优化 1.减少http请求 基本原...
    进击的蒸汽机阅读 227评论 0 0