2017干货第一发 | 有关WebAPP优化方案总结

写在前面

在公司做过项目都知道,一款产品性能的优化非常重要,同时也是体现个人技术能力。

之前一直做算法,随后在公司做平台软件及后台,一个产品开发好-上线,优化一直伴随着整个过程,之前在公司做的一款平台软件,从上线到最终的稳定几乎花了一年时间,其中大部分都在做系统的优化。

优化的前提是软件的业务架构和数据设计的比较好,否则只能推到重来.所以产品的架构和数据库的设计很重要。

言归正转,今天要给大家讲的是webApp的优化,主要利用自己业余接的大大小小6-7款外包项目和帮朋友做的几款项目以及自己平时测试过程中遇到的问题给大家讲讲webApp相关的优化方面的知识,同时很多优化都是参考了大量网上相关的技术,在其基础上进行修改。

这里有说的不好的请大家多多指教,或者有更好的解决办法,望大家能够指出,一起进步!

看点

01

首先给大家列一个提纲:

1.前言

2.优化动力主要来源

3.开发webAPP 有哪几种方式

  3.1 单页web应用,如ExtJS,Backbone,AngularJS,Avalon等
      3.1.1单页应用现状
      3.1.2其中部署上也存在这很大的差异
      3.1.3 单页web局限性
      3.1.4对程序员掌握JS语言程度     
  3.2 基于框架webAPP,如Ionic,React Native,MUI等

4 webAPP优化方案

 4.1 网络传输优化
    4.1.1 网络传输的优化要点
    4.1.2 首屏加速
    4.1.3 降低请求数量
    4.1.4 降低请求量
    4.1.5缓存Ajax/localstorage
    4.1.6 lazyload懒加载        

 4.2 DOM操作优化
    4.2.1 页面渲染
    4.2.2 减少使用定位属性(fixed/absolute)

 4.3 内存资源优化
    4.3.1 虚拟键盘导致fixed元素错位
    4.3.2 fixed元素滑动惯性平滑度
    4.3.3 其它

4.4 内存资源优化
    4.4.1 移动端的javascript
    4.4.2 闭包陷阱
    4.4.3 webapp资源释放
    4.4.4 动画与假死
    4.4.5 Application Cache

 4.5 增强用户体验优化 
     4.5.1 区域滚动
     4.5.2  点击响应

首先来看看,我们给一款产品做优化的来源

看点

02

优化动力主要来源

1)很多优化都是来自于测试部提交的bug

2)用户使用过程中反应的各种问题.

首先大家要明白现在开发webAPP 有哪几种方式及主流框架是什么,这里再给大家总结一下:

看点

03

开发webAPP 有哪几种方式

  3.1 单页web应用,如ExtJS,Backbone,AngularJS,Avalon等

  3.2 基于框架webAPP,如Ionic,React Native,MUI等

那么这两者有什么区别,又有什么优势呢?下面给那大家详细介绍:

3.1 单页web应用

3.1.1单页应用现状

单页应用的流行程度正在逐渐增加,大家如果关注了一些初创型互联网企业,会发现其中很大一部分的产品模式是单页化的。这种模式能带给用户流畅的体验,在开发阶段,对JavaScript技能水平要求就比较高。

单页应用开发过程中,前后端是天然分离的,双方以API为分界。前端作为服务的消费者,后端作为服务的提供者。在此模式下,前端将会推动后端的服务化。当后端不再承担模板渲染、输出页面这样工作的情况下,它可以更专注于所提供的API的实现,而在这样的情况下,Web前端与各种移动终端的地位对等,也逐渐使得后端API不必再为每个端作差异化设计了。

3.1.2其中部署上也存在这很大的差异

现在越来呈现一种“无后端”的Web应用。那么这又是什么呢? 
说的是你的产品很可能只需要自己编写静态Web页面,在某种云平台上定制服务端API和云存储,集成这个平台提供的SDK,通过AJAX等方式与之打交道,实现注册认证、社交、消息推送、实时通信、云存储等功能。

我们仔细观察这种模式就会发现该前后端已经完全分离,前端代码完全静态化,这样我们完全可以把它们放置到CDN上,这样访问将大大地加速,而服务端托管在云平台上,开发者也不必去关注一些部署方面的繁琐细节。

假如你是一名创业者,同时也在做一款实时协同的单页产品,可以在云平台上,快速定制后端服务,把绝大部分宝贵的时间花在开发产品本身上。这样就更加高效,更加的节省时间.

但是它也是有局限的?那么有哪些局限呢?

3.1.3 单页web局限性

1)单页应用最根本的缺陷就是不利于SEO,因为界面的绝大部分都是动态生成的,所以搜索引擎很不容易索引它 
2)用JS渲染的单页面应用性能相对比较差

首先我们来看看浏览器渲染机制:

2017干货第一发 | 有关WebAPP优化方案总结_第1张图片

渲染的步骤:

浏览器通过网络请求加载页面资源,在页面呈现之前无论如何都要经历以下过程:

1)HTML→DOM 
2)CSS→CSSOM 
3)DOM + CSSOM → Render Tree 
4)对Render Tree进行布局计算(Layout) 
5) 对布局结果进行屏幕绘制(Paint)

整个过程都是相对比较耗时的,从而造成性能相对比较差

3.1.3对程序员掌握JS语言程度

一个产品想要单页化,首先是它必须适合单页的形态。其次,在这个过程中,对开发模式会产生一些变更,对开发技能也会有一些要求。 
开发者的JavaScript技能必须过关,同时需要对组件化、设计模式有所认识,它所面对的不再是一个简单的页面,而是一个运行在浏览器环境中的桌面软件。

3.2 基于框架webAPP

基于框架的webAPP 就比较常见的,如果大家还有不懂得,请参考博客中一篇文章. 
[框架之谈]极佳的 JS 移动应用程序开发框架 
这里不再讲述了.下面着重给大家总结一下在开发webAPP 中我们应该注意什么?

看点

04

webAPP优化方案

前端优化分为两个切入点:网络传输与DOM操作,而网络传输是制约一个网站速度的主要因素。 

webAPP 优化主要从以下几个方面去着手:

4.1 网络传输优化 
4.2 DOM操作优化 
4.3 内存资源优化 
4.4 其他优化 
4.5 增强用户体验优化

下面一一来看看各个部分:

4.1 网络传输优化

4.1.1 网络传输的优化要点

零请求,无流量其实说白的就是最大程度的减少请求数,降低请求量。

4.1.2 首屏加速

然而对webapp模式的应用来说,首屏加载慢是一个不可避免的问题,所以提升webapp首屏加载速度是提升整体网站速度的关键。 
现在我们来看看网站首页加载时间,现在我们分别取其150kb与30kb网速的加载速度,可以看出会慢! 

2017干货第一发 | 有关WebAPP优化方案总结_第2张图片

2017干货第一发 | 有关WebAPP优化方案总结_第3张图片
 
如果是webAPP ,我们可以做以下的优化:

1)我们应该避免页面长时间白页,这个时候便提出了fake页的概念。页面渲染只需要完整的HTML以及CSS,这个便是第一个优化点。

2)从数据请求数以及请求量来说,webapp首页的响应应该比较慢,若是任由js加载完成再渲染页面,用户很有可能失去耐心。

3)但是从DOMContentLoaded来看,首页事实上页面响应比较迅速,所以这个加载结束后页面第一屏便渲染结束,然后再异步加载js,当js改变后再动态改变dom结构中的一些关键点

这个时候一个静态HTML页面,装载首屏的基本内容,让首页快速显示,然后js加载结束后会马上重新渲染整个页面,这个样子,用户就可以很快的看到页面响应,给用户一个快的错觉,给人感觉快得多。

4.1.3 降低请求数量

由webapp首页来说,不可避免的使用的js文件较多,这些文件分为两类: 
① 框架js-css 
② 各个业务团队js-css 
所以可以限定每个业务团队只会加载这四个文件,以最小降低请求数,这里又涉及到并行加载,数量与容量有一个临界值,如何取这个临界值需要各位自己去实验

4.1.4 降低请求量

虽说图片压缩是不必说的事情,但是总会有些时候你会发现一些网站的图片尺寸很大,这个需要处理,而且必须处理。

以框架库为例,除了核心包以外,不需要的UI或者功能库可以剔除,用到了再动态加载,减少首次加载量,这个一开始就得做好,做不好后期就不好改

以业务团队为例,首次加载的js与html模板会将常用的几个页面压缩合并,其它页面访问时再请求,若是想提升首屏加载便可以只下载需要的页面文件。

需要注意:

① 若是你们是要的还是jQuery库的话,可以考虑换成zepto了 
② 勿胡乱引用第三方库,若是要引用一定是读懂源码的情况下重写使用之,这样的好处是,吃得透,万一有问题,能改,而不是没办法又换库

4.1.5缓存Ajax/localstorage

该方案的原理与前面类似,我们发送Ajax请求时候,应该缓存一些非实时数据,比如城市信息和常用联系人,但是我们只能缓存非敏感信息, 
产品搜索页至列表页的请求数据会缓存30s-60s,若是过期时间内用户回到列表页的话不会重新请求数据 
这对服务器压力,页面响应皆是有利的,这个在30s内事实上意义不大,可以减少一次请求。 
另外,对于get和post的效率,曾经有人做过一次测试: 
get100次平均耗时323ms;post100次平均耗时589ms,所以post方式是比get慢的,但post请求的优点是安全,并且参数没有长度限制。

是选择post还是选择get,皆需要处理,避免截断url,或者处处post。-

4.1.6 lazyload懒加载

只显示首屏页面,其它内容需要时再加载,比如列表页、图片lazyload,皆需要做

4.2 DOM操作优化方案

DOM操作主要分为页面渲染与资源清理(heap控制),两者之间又相辅相成,若是DOM操作一块处理不好,其产生的感觉就不再是慢,而是卡,所以DOM操作优化的主要目的就是消灭页面卡的问题,这个在移动端尤为重要。

4.2.1 页面渲染

浏览器会解析三个东西:HTML、Javascript、CSS 
浏览器首先会根据HTML生成DOM Tree,其次会根据CSS生成CSS Rule Tree,javascript可以通过DOM API与CSS API操作DOM Tree与CSS Rule Tree,从而引起页面变化。 
浏览器解析结束会通过DOM Tree与CSS Rule Tree形成render tree,只有display不为none的元素才会形成render Tree,render Tree形成后浏览器会调用GUI绘制页面,在此之前做的一件事情便是layout或者说reflow。上面的描述简单而言可以分为以下流程:

1)HTML→DOM 
2)CSS→CSSOM 
3)DOM + CSSOM → Render Tree 
4)对Render Tree进行布局计算(Layout) 
5) 对布局结果进行屏幕绘制(Paint)

在这个过程中,若是javascript动态改变DOM Tree便会引起reflow 
页面中的元素改变,只要不影响尺寸,比如只是颜色改变只会引起repaint不会引起回流.否则,reflow不可避免,这个时候便需要重新计算形成render Tree,reflow分为局部回流与全局回流,会影响下面的,不会影响上面的元素. 
reflow耗用的系统资源较大,DOM Tree中受到影响的节点皆会reflow,然后影响其子节点最坏的情况是所有节点reflow,该问题引发的现象便是低性能的电脑风扇不停的转,手机变得很热,并且非常耗电,以下操作可能引起reflow

l) 操作dom结构 
2) 动画 
3)DOM样式修改 
4)获取元素尺寸的API

4.2.2 减少使用定位属性(fixed/absolute)

static元素处于文档流中,其渲染速度是最快的,我们做过一个测试: 
100个absolute元素与100个static元素渲染时差在0.01-0.007ms 
100000个元素渲染差距便增至30ms左右,这个微小的时差在移动端变得尤为明显,比如: 
小米/三星手机(1000左右),便存在明显的渲染问题,具体表现为:

l)定位元素在手机上不能显示。 
2)定位元素动画效果失效。

以上问题便是UI渲染失效多导致,最好的解决方案是减少使用定位元素,否则只能引起强烈reflow才能解决。 
另外,产品经常会有fixed的相关需求,比如支付按钮一直出现在低端,这个需求会造成两个问题:

l)fixed元素遭遇文本框时失效,可能会飘到页面中间阻挡输入 
2)影响效率

问题一原因与移动端的实现有关,暂时没有完美的解决方案,问题二便与渲染直接关联,滚屏时,页面上所有的像素会跟着滚动,显卡对全屏幕上下移动的处理很快,但是若是出现一个fixed元素或者有元素不跟着一起滚动,那么滚动对手机浏览器来说就是一个负担,这种滚动的性能甚至体现在了iphone 4s,因为滚动可能会造成reflow,这个现象体现在:

使用absolute配合javascript模拟fixed效果时,会有断片的效果,该问题在iphone5s便不会出现这个问题。

4.3 其它优化

当然,我们不能忽略产品的需求,fixed类需求应该在技术上得到解决,还用户一个良好的体验。

4.3.1 虚拟键盘导致fixed元素错位

fixed元素一定会伴随虚拟键盘的出现,但是虚拟键盘只是“贴”在了viewport上,表面上不会对dom产生“任何”影响,但是这个时候fixed元素表现却变得怪异起来,会错位。

应用层面解决问题方案是,虚拟键盘弹出时将fixed元素设置为static,虚拟键盘消失时候设置回来。

由于虚拟键盘出现并未抛出事件,而检测scroll或者resize事件,皆会有一定延迟,会出现闪烁现象,所以现有最好的方案是setinterval定时器监控当前获取焦点元素是否为文本元素,若是是的话便需要处理,如此便可解决fixed元素错误问题。

4.3.2 fixed元素滑动惯性平滑度

我们常常遇到这种产品需求,tab标签栏开始固定,当滚动向下超过该标签栏后便会变成fixed元素,一直出现在头部,这样的需求在电脑上没有问题,但是在iPhone5s以下的手机常常会出现小范围错位或者快速移动大范围错位的问题。

这个时候我们可以引起reflow迫使浏览器重绘以解决这个问题,这里推荐一个奇怪的hack写法:同时设置三个image元素的src属性,便可以全范围解决该难题, 该方案被团队证实并得到应用。

//三图片src,引发reflow,处理fixed方案惯性问题

2017干货第一发 | 有关WebAPP优化方案总结_第4张图片

4.3.3 其它

l)CSS选择器尽量使用id与class,避免过度层叠 
2)避免使用数值,比如:border: none不会引起渲染,而boder: 0会 
3)动画时候让元素脱离文档流,以免导致大量reflow 
4)避免逐条修改DOM样式,改以className实现同样功能 
5)操作DOM时将display设置为none,因为这种元素不会影响渲染,或者操作fragment对象取代操作显示在页面上的DOM 
6)避免将获取DOM样式属性的操作写在循环中,可能引起重复reflow

4.4 内存资源优化

4.4.1 移动端的javascript

首先,移动端的性能与PC端的性能完全不在一个数量级上,比如,我哥做过一个测试,使用innerHTML绘制大段,之后想获取HTML的ID节点,事实上是获取不到的,这种问题在单页模拟多页,动态创建DOM会经常发生

2017干货第一发 | 有关WebAPP优化方案总结_第5张图片

这类问题匪夷所思,因为页面UI渲染与DOM操作是互斥的,但是就算出现了这个问题,一个解决方案是使用settimeout,更好的方案是使用DOMNodeRemoved事件监控页面DOM改变,将我们的DOM操作回调放入以确保渲染结束。

以上问题只是为了说明移动端的性能问题,这类性能问题会导致很多莫名其妙的问题,而且很多与渲染有关。但是这也从侧面说明了移动端资源的紧缺,若是heap值过大,会导致操作出现卡的现象,更有甚者,会引起页面假死直接退出。

webapp的模式,完全依赖于浏览器的垃圾回收,基本就是作死,因为传统页面一旦刷新页面整个资源完全释放,而webapp没有刷新这类操作,只有一个状态到两一个状态,不相关的内存会保留,资源必须手动释放,或者说,框架必须提供垃圾释放的机制。

这个由图表heap值变化可以清晰看出。

而view切换过程中,不用的资源若是不手动设置为null会导致变量得不到回收便脱离框架控制而失控了。

所以我们在webapp的过程中需要注意:

l) 释放没有使用的闭包 
2)观察者需要得到清理 
3) 释放定时器 
4)view切换过程中,在destroy中释放view相关资源

4.4.2 闭包陷阱

在我们工作过程中,滥用局部变量极有可能引起闭包陷阱,这个问题不止是性能问题,在逻辑上会引起错误,而且不易发现,比如,在AMD闭包中使用一个局部变量

如此操作,会改变_ attributes对象,若是一个实例还无问题,但是两个实例的话便会发生变量污染。 
这只是一个例子,但是在代码中滥用局部变量可能会引起不必要的隐忧,戒之慎之。

4.4.3 webapp资源释放

根据前面的描述,我们可以得出一个结论: 
无论是view还是UI组件我们得提供统一的destroy接口,以便让用户继承释放资源。

若是view的资源得不到释放导致heap值过高,webapp模式的网站其价值大减。

这里有几点可以考虑:

1)webapp中view实例保存不超过5个,多了便释放dom结构以及内存引用(临界值自己判断最优) 
2)view隐藏时释放内部资源,解除DOM事件句柄 
3) UI组件与view相同,需要统一释放机制

但是单页应用由于页面不会刷新,总有一些资源得不到释放,此问题任重道远

平时编写过程可以做以下优化:

1) 使用函数替换逻辑

让我们的函数产生一个返回值替换函数中的大段逻辑,这样的第一个好处便是逻辑清晰,第二个好处是这些函数在不同的函数中,这个函数被使用后便会自动得到释放。

2) 清理闭包引用

当一个闭包函数或者什么使用结束后,若不会再使用,便需要手动清理该变量,以便解除闭包之间的引用关系,从而释放资源。

3) 使用对象属性或者方法

一个对象可以引用其他对象的属性或者方法,比如obj.foo = thatObj;这种情况下,我们可以随时删除对象解除引用关系,然后便可以清理资源。

4.4.4 动画与假死

动画而言建议采用CSS3实现动画,CSS3中又推荐采用最新的接口,比如使用transform取代top/lelf操作,这样操作效率搞得多。

若是采用动画可以将对应元素设置为absolute以减少回流,另外最关键一点还是避免移动DOM树过多的节点,这个时候需要驳回产品无理需求,比如:

产品要求日期滚屏组件,显示半年的数据,这半年的数据便是180个DOM树

这个级别的DOM一旦移动整个手机会直接卡死,甚至构建DOM树,渲染页面也会出现假死现象,该问题需要规避。

4.4.5 Application Cache

Application Cache是HTML5为webapp离线使用而增加的API,与localstorage、cookie等不同,Application Cache存储的是一系列请求资源允许浏览器在请求资源时不必通过网络,设计得当的话可以实现离线应用。 
使用Application Cache主要是在网络性能上提升,有效降低了网络延迟,提升请求加速.

2017干货第一发 | 有关WebAPP优化方案总结_第6张图片

4.5 用户体验优化

4.5.1 区域滚动

2017干货第一发 | 有关WebAPP优化方案总结_第7张图片

就官方的例子便会出现以下问题:

1)头部消失

2)偶尔不能显示文本框焦点,或者焦点错位

若是以上问题可忽略,但是文本框不见了这种事情,我是不会接受的

导致的原因与组织浏览器默认事件有关,所以,我这里不太推荐各位大范围的使用区域滚动,而改在区域使用,

就去哪儿的ipad版本在一个具有文本框的地方使用了IScroll,其提高的用户体验与导致的问题一样引人入胜。

事实上,小钗及其推崇IScroll库,虽说他有这样那样问题,但是,IScroll是最有可能带来移动端革命的库,因为他可以:

① 解决webapp区域滚动

② 变相解决fixed问题

③ 解决动画过程带来的长短页问题

总而言之,IScroll方案的提出,是让webapp媲美native app靠近了一大步,真正的平起平坐还需要浏览器的支援

4.5.2 点击响应

click本身在移动端响应是没有问题的,但是我们点击下来300ms 的延迟却是事实,这种事实造成的原因就是 
手机需要知道你是不是想双击放大网页内容 
所以click点击响应慢,而touch却不会有这样的限制,于是移动端的touch相当受欢迎,至于鼠标慢,他究竟有多慢,我会告诉你每次会慢300ms 

2017干货第一发 | 有关WebAPP优化方案总结_第8张图片

你可能感兴趣的:(2017干货第一发 | 有关WebAPP优化方案总结)