前端性能优化小结

  1. http优化,加大并发,减小请求数量以及传输量
  • domain hash技术突破并发限制。http1.x浏览器对于发起的链接有并发限制,这个限制是针对域名的,因此将静态资源放在多个不一样的域名下,也能够突破这个限制。可是也不宜使用太多域名。会增长额外的dns解析成本。
  • 合理使用http头。使用expires,cache-control,Etags等http头缓存静态资源。这篇文章介绍的很详细:https://zhuanlan.zhihu.com/p/...
  • Connection:keep-alive。保持tcp链接。避免三次握手以及tcp的慢启动开销。
  • 合理利用空闲时间作一些预操做。预测用户的大几率行为,在页面空闲时加载后续所须要的资源。dns预解析。TCP预链接。页面预渲染。有一些标签属性已经能够很好的作到这些,如prefetch & preload & dns-prefetch。
  • 合并css,js文件。
  • 图片压缩以及页面须要多大的图片就请求多大的图片。好比页面只显示20*20的图片,就不要返回一个500*500的图片。
  • cdn加速。
  • gzip压缩。
  • 减小没必要要的通讯量,好比合并发送上报数据。
  • 按需加载模块资源。好比js,css。
  • 使用http2。
  1. 缓存请求,并保持缓存内容大小与性能之间的平衡。好比某个请求涉及大量的数据库操做,耗时很长,而且有必定几率屡次请求。在这个数据的实时性和重要性不是那么强的状况下,咱们能够将请求结果缓存到变量中或浏览器的一些别的存储机制中。可是缓存内容过多也会对性能有影响,因此咱们也要根据必定的规则(好比访问频率,访问前后时间,缓存总数量等)及时地清除部分缓存。若是不想改动代码,那么http响应能够返回Expires http请求头,在过时以前就再也不发请求。
  2. cookie优化,减小cookie传输量
  • 避免cookie太庞大。不要什么都往cookie上放。cookie的主要做用在于身份识别,而不是信息存储。由于每一个请求都会带着cookie,无形中会加大不少传输量。前端的话可使用一些其余的替代存储方式。好比localStorage,sessionStorage。
  • cookie free技术。将一些静态资源放在与主域不一样域名的服务器上,浏览器请求的时候就不会带上主域的cookie了,从而减小传输量。
  1. Bigpipe技术。产生于Facebook公司的前端加载技术,它的提出主要是为了解决重数据页面的加载速度问题,是一种数据渐进式预加载方案,基于HTTP Chunk。
  2. PWA技术。service worker。
  3. 避免空的src和href。
  4. 图片懒加载。lazy load。
  5. 脚本加载优化
  • script标签放到页面最后,</body>标签前面,避免阻塞页面渲染。一个讨论:https://www.zhihu.com/questio...
  • 合并,压缩脚本。减小链接数和数据传输大小。
  • 无阻塞的脚本css

    • script标签添加defer,async属性。
    • 动态生成script标签。使用onload事件或onreadystatechange事件来检测脚本加载完从而执行加载完以后的回调。
    • 使用ajax方式加载js内容。插入一个script标签中。好处是加载完以后不会当即执行。
  1. JS数据存取
  • 减小做用域查询。做用域链的查询,变量的位置越深,查询速度越慢。而全局变量在做用域链最深。因此,对于使用一次以上的跨做用域变量咱们应该把它用局部变量存起来。
  • 避免内存泄露。html

    • 循环引用
    • IE,闭包中有dom对象。
  • 减小嵌套成员的查找。可缓存在局部变量中。相似var Dom = YAHOO.util.Dom;
  • 减小原型链查找。
  1. dom优化
  • 减小dom数量。若是页面dom数量太多,对性能是有影响的。
  • 减小dom访问与修改。dom与JavaScript至关于两个独立的部分以功能接口链接,会带来性能损耗。
  • 尽可能不要在循环中更新页面内容。一个更有效率的版本将使用局部变量存储更新后的内容,在循环结束时一次性写入。
  • 不建议用数组的 length 属性作循环判断条件。访问集合的 length 比数组的length 还要慢,由于它意味着每次都要从新运行查询过程。
  • 使用快的API。好比document.querySelector()。
  • 事件绑定。前端

    • 多使用事件代理,而不是每一个dom节点上去都绑定事件。
    • 考虑使用自已定义的事件管理器,一个dom上不要反复绑定事件。而是维护一个事件回调数组,像jQuery作的那样。
  • 减小回流与重绘。css3

    • 少使用.style一个属性一个属性地去改。而是合并到一块儿一块儿修改。好比用class来控制样式,或者cssText来批量修改。
    • 让要操做的元素进行"离线处理",处理完后一块儿更新。
    • 回流必将引发重绘,而重绘不必定会引发回流。
    • 减小对位置信息的属性读取以及getComputedStyle与currentStyle的使用。浏览器会维护1个队列,把全部会引发回流、重绘的操做放入这个队列,等队列中的操做到了必定的数量或者到了必定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让屡次的回流、重绘变成一次回流重绘。若是代码中频繁读取实时位置属性,会致使浏览器屡次重排。引发性能问题。
  1. 异步优化任务。分割任务异步执行,让出线程。
  • 若是用户的操做100ms得不到响应,用户就会感受到与应用失去联系。若是咱们的代码执行时间太长,用户其余的操做得不到响应。因此若是咱们没法减小脚本执行时间,咱们可能考虑主动地让出线程。分解任务,异步执行。

好比分解成多个任务使用setTimeout或setInterval来异步执行。git

  • 可是若是咱们任务分得太细,好比每一个循环体算成一个任务,每一个任务结束就让出线程,效率就很低了,由于setTimeout 和 setInterval 原本就设计的慢吞吞的,即便延时时间为0,浏览器环境下每秒也最多执行几百次。而换成while循环,每秒能执行几百万次。 因此咱们每一个异步任务中应该多处理一些任务,好比咱们让它执行50ms。在每一个异步中检测一下执行时间,加入while循环,时间若是小于50ms就继续执行,超过50ms就让出线程。这样既保证了不阻塞线程,也让咱们的任务能尽快地完成。
  • 使用Web Workers。
  1. ajax的优化。目前一些比较成熟的库的ajax都是在ajax彻底接收完响应以后才执行成功的回调。这里其实有很大的优化空间。
  • 通常的ajax封装是在XMLHttpRequest的readyState==4(整个请求过程已经完毕)的时候进行成功回调处理。而其实在readyState==3的时候(响应体下载中,responseText中已经获取了部分数据.)已经能够对已经接收到的部份内容进行处理了。好比几十万条数据从后端传过来,要插入dom。若是咱们等到全部数据接收完毕,再一次性插入dom,可能会有很大的性能问题。可是若是咱们在后台将数据以必定的方式拼装,而后前端接收到一部分处理一部分,就有两方面的性能提高,一方面是提早处理了数据,让用户能够更早地看到数据效果,另外一方面是分解了任务。
  • 合并请求。好比多个图片base64格式加分割符一块儿发送过来。前端再把结果分割,分发到多个img标签上去。
  • 数据传递格式。不必定非要是json格式。其实能够很灵活。自定义的格式一方面能够减小数据传输量,另外一方面更方便前端边接收边处理。
  1. 循环与递归
  • 尾调用优化。会将从内存中清除前面的调用栈,将调用栈清零。一方面是内存释放,另外一方面是避免了调用栈溢出引发的错误。
  • 减少循环次数。每一个循环体中多执行几个循环内容。
  • 减小循环体开销。好比使用倒序循环。
  • 缓存计算结果。使用Memoization技术来避免重复计算。
  1. 函数的节流与防抖,限制函数主体执行频率。频繁执行某些函数会严重影响性能,好比一些常见的触发频率很高的浏览器事件,若是每次触发都去执行回调甚至操做dom,性能影响很大,而且咱们肉眼对dom变化的实时性要求并无那么高。因此须要限制主体内容的执行频率。工具库underscore中提供了对应的_.throttle和_.debounce方法。
  • window对象的resize、scroll事件
  • 拖拽时的mousemove事件
  • mousedown、keydown事件
  • 文字输入、自动完成的keyup事件
  1. requestAnimationFrame方法。
  2. 逻辑优化,减小耗时操做。不少功能并非只有一种途径去实现。若是一种操做特别耗时。也许能够优化一些逻辑就减小这样的操做。
  3. 定时器的控制。

应用中存在过多的定时器会影响性能。特别是单页应用中,若是咱们定义了一些定时器而没有随着场景消失而清掉定时器,还可能会产生不少逻辑上的问题。github

  1. 正则表达式优化。
  2. css gpu加速。

欢迎补充交流。github地址:https://github.com/liusaint/l...ajax

参考:
相关文章
相关标签/搜索