提高现代web app中页面性能

提高现代web app的中的页面性能

前言,本文翻译自https://docs.google.com/presentation/d/1hBIb0CshY9DlM1fkxSLXVSW3Srg3CxaxAbdocI67NCQ/edit#slide=id.g32e52b1ea6_1_0看到以后感受讲解的系统清晰明了,实属一篇好文。就加上本身的理解翻译了一下,聊以加深印象。
css

硬件、网络,对性能的而言始终不能避开的两个物理因素

1、 硬件如何影响性能

硬件(即处理能力)决定了计算密集型任务的表现
浏览器必须解析、编译并执行全部的js,以下如所示:

对于每一个阶段而言,代码量的差别显然会影响其变现即影响性能,这种差别在低处理能力的机器上的体现尤其明显。
固然其余类型的资源请求也会影响性能,相比之下js的影响是比较突出的。
因此考虑不一样用户cpu的情况,减小js怪物(即缩小js体积)是很必要的。能够从如下几方面着手:html

  1. 删除没必要要js
  2. 延迟加载非关键js
  3. 借助相关工具webpack

    1.1 删除没必要要js

    只在必要的时候进行转换

    仅仅对须要ES5的客户端才进行转换,80%的浏览器已经支持ES2015。(结合本身实际开发状况,移动端而言确实80%+的手机已经支持ES2015,仅仅只遇到oppop,vivio这两中手机不支持。)由于转换以后的代价仍是有的,以下所示:git

//ES2015
books.map(b => b.title);
//ES5
books.map(function(b) { return b.title; }, this);
//体积大了一倍

使用压缩工具/优化工具

像UglifyJS & Closure Compiler 之类的工具,在压缩以外还有一些优化功能。
对大多数的js而言压缩代码中空格移除和符号修改占了95%的工做量,并不是是精心的代码转换。
压缩不该该是盲目的,应该平衡下面几点。github

  • 更好的压缩比
  • 高额的计算机资源消耗
  • 前期准备
  • 可能的反作用
    压缩可能不是一味的追求体积更小,相对而言,压缩也应该权衡一下其余方面。比较常见就是代码压缩时相比于其余流程,超长的时间消耗。压缩以后可能遇到关键字的问题。
    如何解决其实应该是从自己项目出发。
  • 尽量的优化可缓存的静态资源
  • 在压缩体积和时间之间找到一个平衡点

使用tree-shaking移除没用的代码

和压缩代码的目的一致,减少资源大小,不过是从另外一个层面的解决方案。像webpack,rollup都提供了该功能。
tree-shaking会将没有被用到的exports移除web

//tool 
//used
export function a(){
    console.log('1')
}
export function b(){
    console.log('2')
}
//app.js
import {a} from './tool'
a()

function b 未被使用,最终的打包文件中b将会被删除。浏览器

ES2015的模块是静态的,可使用tree-shaking

import/export 在执行以前就被肯定,而且二者只能在顶层,没有条件逻辑的状况下使用(毕竟未执行)缓存

tree-shaking的局限

  • 仅仅删除未被使用的导出
  • 不支持全部的代码库(仅仅ES2015)
  • 可能作不到极致
    难以肯定删除是否会有反作用,这种打包器只能保留

自我排查

工具不能作到尽善尽美,而且在执行以前肯定某项问题是困难的。
当前来讲应该从代码规范和代码注释来自我完善。服务器

对于框架

若是非必须,请不要使用。大的框架至少300kb的体积。
固然必要,请基于下面几点来选择:网络

  • 服务端渲染
  • 懒加载
  • 代码优化
  • 性能

1.2 延迟加载非必需js

先看一下js不一样引入方式的差异

默认方式 Async Defer
阻塞渲染
执行时机 加载完成 加载完成 document解析完成

使用代码分割和懒加载

  • 减小启动时须要加载的js
  • 尽量少的加载不相关的js
    传统的作法是加载Bundle js,代码分割是将代码分红不一样的chunk
    这里一样有两种极端:
  • 每一个模块对应一个js
    很差压缩
    利于缓存
    粒度更小
  • 整个应用只对应一个js
    便于压缩
    不利于缓存
    粒度太大,便可维护性
    突然有种中庸的感受了,凡事皆有度,全部单一操做都不能过度苛求极致,兼顾才是合理

    1.3 使用其余工具

    使用html和css

    某些情况下可能须要vanilla JS(即原生js),框架带来便利的同时不可避免的有其余的一些性能消耗。提到这里有一篇文章你们能够看一下我是怎么把个人 React 应用换成 VanillaJS 的(这是否是一个坏主意)
    举个例子:
    Netflix 下降了他们登陆页50%的TTI(传输时间间隔)经过下面的方式:
  • 使用原生js来代替React
  • 当用户登陆的时候加载余下的部分

使用server

将代价昂贵的库放到server端,使用ssr来代替client-side-render.
ssr能够将咱们初始页面加载事件减小到原来的1/5并减小不一样浏览器之间的差别。
ssr确实首屏的优化确实很大,优势很少说。但这里提一句,不要盲目ssr,特别是初次请求响应时间较长的接口

2、网络的影响

首先了解两个概念:

  • 带宽: 数据吞吐量(比特/秒)
  • 延迟: 延迟数据传输时间(ms)

对于大部分市场来讲,带宽是能够知足需求的(这里统计是国外的,平均26兆,国内略低一点),平均页面大小3.5Mb。传输时间(3.5/26)0.13s。国内会差一点。
延迟对性能影响比较明显。
移动网络的延迟

网络 延迟ms
5G <=4
4G <=100
3G 100-500
3G 300-1000

适应移动网络的限制

应该从下面几方面来分别考虑。

  • 减小请求数量
  • 优化关键路径
  • 减小请求大小

2.1 减小请求数量

新建一次链接的代价是昂贵的,要重复如下过程

创建链接须要1至3+响应在数据相应以前。

  1. DNS 查询(可能)
  2. TLS 握手(可能)
  3. 请求资源

初始状态链接不能被充分利用

TCP slow-start限制了在初始响应里里数据被发送的数量

发送更多的数据一般状况下比新建链接要划算。

请求的体积与相应时间并非线性关系。
两次50k的请求消耗比一次100k的大了很多。

减小重定向的使用

  • 重定向增长了服务器昂贵的循环
  • server-side 相对于client-side来讲重定向优秀一点(快而且可缓存)
  • 看一下301和302的响应code

使用缓存

理想状态下,确实资源是否最新不该该经过网络请求
能够经过下面的方式:

  • 使用Content-addressed URLs:
    即内容与地址对应,log13234d.jpg而非log.jpg
  • 使用max-age

这种浏览器调整为Facebook节省了60%的请求

使用service workers来加强缓存

service worker能够帮组咱们:

  • 拦截网络请求
  • 访问浏览器缓存
  • 代替发送网络请求来处理过时的资源

使用http2

使用HTTP2时,每一个来源只须要一个链接,减小了链接建立的开销。

2.2 优化关键路径

优化页面渲染或者加载时所需的事件以便尽量的加快完成。

浏览器优化资源请求

对于全部的请求,浏览器对其是有权重处理的,即分不一样的优先级来加载。具体来讲就是重要会阻塞渲染的优先级比较高。
以下图所示:

使用资源提示

经过如下方式,提早加载或者请求将要用到的内容:

  • Dns-prefresh
  • preconnect
  • Preload(当前页面)
  • Prefetch(下个页面)

2.3 下降请求大小

  • 使用Brotli压缩
    相对于gzip
    更好的压缩比,文件越大越明显
    更快的解压缩
    压缩速度极大提高
  • 减小js体积
  • 优化图片
    23就再也不多提了,方式有不少。

结束语

对于好的资源,多读收益仍是很明显的。此次翻译感受体会又多了一些,不过因为本人才疏学浅,若有错误还望多多指正。一言概之,共同窗习。更多请移步

相关文章
相关标签/搜索