Home  >  Article  >  Web Front-end  >  HTML5实现APP和原生方式有多大差距,多少坑?

HTML5实现APP和原生方式有多大差距,多少坑?

WBOY
WBOYOriginal
2016-06-07 08:42:131701browse

回复内容:

写过一些纯H5的APP,虽然开发起来的确很快很舒服,但和原生比起来纯H5APP还是有很多问题,主要聚集在以下几个方面:
1、动画
动画有很多种,比如侧边栏菜单的滑入滑出、元素的响应动画、页面切换之间的过场等等,在H5之下的众多实现方法都没有办法达到纯原生的性能。一般这些的话有几种不同的选择:css3动画javascript动画原生动画
css3动画非常的消耗性能,如果某一个元素用到css3动画可能还看不出来,但大面积或过场使用css3动画会让app低端手机体验非常差。最好的选择一般是通过框架调用底层的动画,但不管怎么样等于在原来的代码上包上了一层,性能还是不可避免的受到影响。

比如在一个新页面的载入上,如果调用底层动画要考虑的问题有两个,一个是本身资源页面的渲染问题,另一个是远程数据的获取。即便是这些动画能够很快的响应,但大量的css页面会导致渲染卡顿,滑入时可能会有白屏/机器卡顿的现象。为了解决这些性能问题又必须要用到预加载或模拟动画。即便是这样,滑入滑出的动画在低端的安卓机器上还是有很多问题,如果获取服务端数据处理的方式不合适,卡顿白屏的现象会更严重。具体看下面的数据获取方式。

2、获取服务端数据
首先要接受的是,这里的数据获取都是在资源页面上异步完成的,因为只有这样才能让这些资源页面完成预加载或者渲染。但是异步拿到的数据在填入页面中时可能会涉及DOM操作,众所周知,DOM操作非常消耗性能,如果页面小还好,页面稍大数据稍微复杂一点,频繁的DOM操作会导致明显的闪白
而且最重要的一点是,如果页面加载进来之后数据更新的速度太慢,也会让页面模板等待很长时间,对用户体验又不友好,总不能每次打开都像浏览器一样等待刷新是吧。

这个问题如果没有得到解决,H5APP是很难承担大规模数据的页面,在它们之中频繁切换更是难上加难,那么肯定有人也会想到用MVVM的方式,其实我也写过一些基于MVVM的H5APP,相对来说它们获取数据和更新数据的方式更敏捷更科学,但写的过程中又要注意很多H5独有的问题,这些问题在下面的页面切换里来讲。

3、页面切换

上面我们看到了几种不错的实现方式,比如预加载和模拟动画,甚至有批量的预加载,批量的截图模拟动画等等,虽然看起来很友好解决了不少问题,但事实上如果页面足够多就会引发另一个问题:页面的生存周期

试想一下,如果引导页或者主页面缓存了5个子页面的资源,在跳转到响应的子页面时又会缓存这些子页面的下级页面资源,如此反复肯定会占据大量内存使APP的体验下降。那么怎么知道那些页面是需要的,最多缓存多少页面,什么时候结束哪些页面的生存周期呢?在我用过的很多H5APP的框架里都没有对这些问题有一个完美的解答,因此在页面较多内容较多的APP中可能会因这些资源分配的问题降低性能。

这时候我们回过头来再看看MVVM的数据加载问题,实际上不管哪个MVVM框架,写过的人都知道管理这种新型的前端代码最重要的问题是内存的问题,你既要保证代码写的足够优雅没有任何内存泄露问题,也要考虑到在页面生存周期结束时它们的控制器/页面资源是否得到释放,这对全局有没有什么影响,在多个请求时也要合理的分配资源,甚至是复用这些父级页面传过来的缓存资源等等。较小的APP可能并不会有这些问题,如果你想用纯H5来开发大型APP,这很可能会浪费你很多时间——而且结果还不会让你满意。

4、Android/iOS的区别
很多人都说纯H5APP一次编写就能编译Android/iOS两种不同的APP,大大降低了成本。实际上这个观点本身就是值得怀疑的,如果你写过这类APP就能明白我在说什么,它们既不省事,又存在很多BUG,调试时尤其繁琐。
举一个很简单的例子,Android和iOS在返回上一页的处理方式上就有明显的区别,iOS的顶部bar在全屏下怎样处理,Android机器出现smart bar怎样处理页面的布局,调用底层硬件时怎样区分不同的场景等等,你需要写一个又一个机型和系统的判断,然后分别在Android和iOS下调试,最后你却发现这并没有卵用,累的要死却什么没学到,只有一堆不知道什么时候会过时的经验。


现在做H5混合APP开发的人很多,但是纯H5却很年轻,很多问题都没有很好的解决,这几个是我在做这些APP时考虑最多的问题。当然大家也不必担心,随着ES6的推行,硬件发展越来越快,纯H5APP未必没有一席之地。最后说一个很少人注意到的H5优势,大家大谈H5APP时都是快速开发、低成本、多平台等等,但我却觉得它和很多APP开发方式相比有一个不同之处——图文混合的排版。
正是这些复杂多变的CSS样式消耗了性能,但是它带来了排版的多样性,能够细致到每一个字宽行高和风格的像素级处理,才是H5的优异之处。 我试过用国内的 HBuilder + MUI 框架开发,也试过 Cordova + React for Web 开发。现在手上的某App,正在同步使用 Cordova + React 和 React Native 分别开发 UI 层(逻辑层代码公用)。当然,都是小型应用,还不需要像 @李维特 写的一样考虑页面切换等问题……

我的结论是:坑、好大的坑、虎纹大坑

才疏学浅,只总结出以下问题:

1. 性能问题
先是动画。
无论是 CSS3 动画、还是 Canvas 动画,还是 JavaScript 操作 DOM 的动画,都卡;后者尤甚。高端机尚可,低端机是可以卡成幻灯片的。我录过 GIF,使用的设备是台电P88,全志 CPU 。大概就是这样:zsxsoft.qiniudn.com/upl

其次,是 DOM 性能问题。
感谢 React 带来了 Virtual DOM,部分解决了局部区域 DOM 刷新时的性能问题。不过,一旦涉及到较大区域 DOM 更新,反倒有更大的性能损耗(最终计算出来的结果还是要全部替换掉,多做了一步 Diff )。

因为性能问题,Facebook 2012年离开了 HTML5 App 阵营(Facebook: “Betting on HTML5 Was a Mistake”)。但时至今日,还是没有什么改善。也分享一篇文章,可以看看坑:移动端HTML5游戏性能优化
这里有个例子:微众银行 App 是 Cordova + Ionic + Angular。微众很行app十分卡顿,大家觉得么?

2. 兼容问题
先只算官方系统。Android系统的 WebView 一般随 Android 版本更新(当然,也可以自己去 Play Store 更新),每个版本所支持的功能均不同。坑的是,在国内的环境下,基本不会再更新了。有的功能,在 PC 上对应版本的Chrome 是有的,到该版本 WebView 就没有了。
比如说,XMLHttpRequest 的 onprogress 在 Android 4.0.4 上不被支持。于是,针对这类系统,只能采用像之前对 IE 的 Hack 一样,用 iframe 来替代进度条。
再比如说,ECMAScript 6 被高版本 WebView 支持。如果开发者写惯了后,引入了 Symbol 等,又忘记了 polyfill 。在低版本 WebView 就会出错。就像我这样: doesn't support old browsers. · Issue #1685 · callemall/material-ui · GitHub
接着呢,感谢 ROM 厂商乱改系统自带的 WebView ,从而导致在各种小细节上不同手机的显示效果或运算结果不同。更倒霉的是,有的甚至还会全页面混乱。
怎么解决?个人认为,像微信那样自带一个 X5,也许算是一个解决方案吧。

至于兼容问题的例子,还是微众银行好了:v2ex.com/t/215728 (与新版 iOS 9 的 WebView 不兼容)

3. 调试问题
先吐槽:Android 5.0+ 的系统内的 WebView ,可以用 Chrome for PC 来调试。但需要翻墙。


调试分调试 JavaScript 和界面两方面。
JavaScript 方面,如果 throw 出一个错误,很可能剩下的事情你都干不了了。手机端的表现就是什么操作都没用,也不会崩溃退出之类。在开发时,对于 JavaScript 报错,MUI 和 Cordova 均可以通过 adb logcat 来检查报错;Release 后可就没办法找用户连 USB 了。weinre 等工具对于 JavaScript Debug 没啥用。
那 weinre 干啥用?只是让你看 DOM 层级或动态执行代码罢了。这就是 UI 方面的调试了。这部分的话,考虑到兼容问题,自求多福吧……

Cordova 提供了 Ripple,倒的确是一个很不错的解决方案。但是并不能涵盖所有的手机……

4. 代码安全性问题
正如.apk -> .dex -> .jar -> .class -> .java一下就能把代码全部拿出来看一样,.apk -> .js 更为方便,解压一下就好了。于是,在 Release 前,必须 gulp / grunt 构建工作流,把 uglify 之类全部一股脑塞进去。这部分和做网页前端没啥区别,差别大概只有不需要考虑代码切分等(毕竟没有网络,全在本地)。
然而,这样的代码,修改成本非常低。比如我做一个付费的本地游戏,只要简单地修改一下.js,轻轻松松破解验证等后重新打包回去,破解版游戏就做好了,比 Java 的简单多了。就算有 C++,我 js 不调用你,你又奈我何?没有服务器验证的话,玩蛋去吧。

5. 功能问题
如果没有 Native Code,一切HTML5 App都是空架子。所以,Java / Objective-C / C#仍然是必须学习的语言;Native App 如何开发也仍然是必修。比如以下代码,就是在 MUI 里用原生浏览器打开一个链接。
<code class="language-js"><span class="kd">function</span> <span class="nx">openInBrowser</span><span class="p">(</span><span class="nx">originalUri</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">Intent</span> <span class="o">=</span> <span class="nx">plus</span><span class="p">.</span><span class="nx">android</span><span class="p">.</span><span class="nx">importClass</span><span class="p">(</span><span class="s2">"android.content.Intent"</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">main</span> <span class="o">=</span> <span class="nx">plus</span><span class="p">.</span><span class="nx">android</span><span class="p">.</span><span class="nx">runtimeMainActivity</span><span class="p">();</span>
    <span class="kd">var</span> <span class="nx">Uri</span> <span class="o">=</span> <span class="nx">plus</span><span class="p">.</span><span class="nx">android</span><span class="p">.</span><span class="nx">importClass</span><span class="p">(</span><span class="s2">"android.net.Uri"</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">uri</span> <span class="o">=</span> <span class="nx">Uri</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">originalUri</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">intent</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Intent</span><span class="p">(</span><span class="nx">Intent</span><span class="p">.</span><span class="nx">ACTION_VIEW</span><span class="p">,</span> <span class="nx">uri</span><span class="p">);</span>
    <span class="nx">main</span><span class="p">.</span><span class="nx">startActivity</span><span class="p">(</span><span class="nx">intent</span><span class="p">);</span>
<span class="p">}</span>
</code>
H5 APP 最大的两个坑,一个是 CSS, 一个是DOM。

DOM 的设计初衷是跟交互体验相驳斥的。

我们直接用 canvas / webgl 渲染引擎做 H5 APP,在 ios 和 安卓5 以上的设备体验跟原生APP基本无差,在交互体验上能够好过原生APP。 但是缺点是控件太少,很多需要自己写。 可以用的渲染框架有很多,比如: cocos2d-html5, pixijs, two.js

我用下来,感觉效果最好的实现方案是 cocos2d-h5 + svg texture + react router 最近也算晚的比较多了,碰到几个神奇的坑
1、软键盘
弹出来回不去,blur事件时有时没有,额,简直想砸手机
2、动画点不到
animation中的元素点不到,妈蛋,怎么点都不容易点中,ios尤其悲剧
3、内存
用angularjs一下,不控制内存就搞崩了
4、css
各种css的不兼容的坑,响应式也要根据不同机型来做适配,简直生不如死 虽然有坑,跳进去,总比站在坑外等死强!随着各类APP 框架的出现,已经越来越完美的解决了HTML5开发APP的短处,至少说不会JAVA、不会OBJECT-C的人,也能搭上一条船,谁也不知道船能走多远,走多快,觉得这个是方向就勇敢的去尝试 这个坑还挺大的,如果业务逻辑、界面渲染比较复杂,对动画有要求的话,H5会遇到很多问题。

前面也有答主说了,webview的性能问题,高端机和低端机差异很大,安卓5之后和安卓5之前差异也大。这里补充一点,安卓的微信用的QQ浏览器X5内核也是一个巨坑,如果应用要求用微信访问的话,简直痛苦。

相对来说IOS就好很多,除了i4和以下的性能不够以外。

目前我们用framework7的ui框架+react开发,phonegap打包,轻量级应用没什么问题。

额外说说framework7框架,有IOS和Meterial两种风格,我们只用了IOS的,因为Meterial动画元素太多,低端机卡成狗了要… 要说有坑,最大的坑还是bug可以线上fix了,于是经常会被半夜喊起来改bug…… 赞同楼上几位的看法,h5的优势是图文混排,开发的便利性,以及丰富活跃的前端社区,最起码对于前段来说不同的屏幕,用css布局极其方便。我用过hbuilder,cordova,apicloud之类的,觉得目前最成熟可靠的方案是cordova,无论是插件的质量,还是社区的活跃度,都是其他无法比拟的,最起码你要踩的坑google一下,别人都踩过了,有了解决方案。

至于框架组合,我推荐vue+framework7,用的很顺手。android统一推荐搭配crosswalk,性能有明显提升,这也是用cordova的一大优势。楼上说的兼容性,我这倒是没啥问题,android,ios都成功上架了。 平台标准不统一,性能差异性过大,等等等等,反正各种神坑坑的连骨头渣都不剩
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn