跨平台开发必须对前端和客户端都有所了解,并且起码熟悉前端、iOS或者Android中间某一端的开发。即使如此,在不熟悉的领域如果没有做好足够的调研,也很难在现实的技术选型中快速做出最适合当前情况并兼顾到项目的长期发展。
目录
一、单页面应用(SinglePage Web Application,SPA)
二、多页面应用(MultiPage Application,MPA)
一、单页面应用(SinglePage Web Application,SPA)
只有一张Web页面的应用,是一种从Web服务器加载的富客户端Rich Client,单页面跳转仅刷新局部资源 ,公共资源(js、css等)仅需加载一次,常用于PC端官网、购物等网站。
二、多页面应用(MultiPage Application,MPA)
多页面跳转刷新所有资源,每个公共资源(js、css等)需选择性重新加载,常用于 app 或 客户端等。
|
单页面应用(SinglePage Web Application,SPA) |
多页面应用(MultiPage Application,MPA) |
组成 |
一个外壳页面和多个页面片段组成 |
多个完整页面构成 |
资源共用(css,js) |
共用,只需在外壳部分加载 |
不共用,每个页面都需要加载 |
刷新方式 |
页面局部刷新或更改 |
整页刷新 |
url 模式 |
a.com/#/pageone |
a.com/pageone.html |
用户体验 |
页面片段间的切换快,用户体验良好 |
页面切换加载缓慢,流畅度不够,用户体验比较差 |
转场动画 |
容易实现 |
无法实现 |
数据传递 |
容易(在一个页面内,页面片段间数据传递很容易实现) |
依赖 url传参、或者cookie 、localStorage等 |
搜索引擎优化(SEO) |
需要单独方案、实现较为困难、不利于SEO检索 可利用服务器端渲染(SSR)优化 |
实现方法简易 |
试用范围 |
高要求的体验度、追求界面流畅的应用 |
适用于追求高度支持搜索引擎的应用 |
开发成本 |
较高,常需借助专业的框架 |
较低 ,但页面重复代码多 |
维护成本 |
相对容易 |
相对复杂 |
结论:SPA由于有很多好处,已经是WEB应用开发的潮流,特别是移动应用开发,但在Weex跨平台开发上尚需探讨。
附:单页多页比较
- 单页的优势
- 单页主要优势在于不存在页面切换问题,因为只在同一个页面间切换,会更流畅,而且可以附加各种动画和过度效果,用户体验更好。
- 还有很重要的一点是可以用到vue的路由和状态保持,不用担心切换造成的数据不同步。
- 打包方便,有现成的脚手架可以用,也比较不容易出问题。
- 单页的劣势
- 所有逻辑和业务都在一个页面上,逻辑上不是很清楚,当业务变得复杂的时候改动起来就比较麻烦。
- 鸡蛋都在一个篮子里,只要一个地方出现错误,可能导致整个页面出错。(是后文所谓的“白屏”问题原因之一)
- 所有代码都在一个页面,首次加载耗时较长,页面体积较大。(缓存+压缩)
- 多页的优势
- 逻辑清楚,各个页面按照功能和逻辑划分,不用担心业务复杂度。
- 单个页面体积较小,加载速度比较有保证。
后续业务可能会变得更复杂的话,技术一般更偏向于逻辑上比较清楚的多页面模式。
- 多页的劣势
- 重复代码较多。
- 页面经常需要切换,切换效果取决于浏览器和网络情况,对用户体验会有一定负面影响。
- 无法充分利用vue的路由和状态保持,在多个页面之间共享和同步数据状态会成为一难题。
- 打包流程会相对复杂一些。
三、为什么当前产品XXX端采用跨平台开发?
- 为什么不用原生?
需求有100多个页面,原生4-6个页面每人周,当前的开发人手不可能在30天完成。
项目管理者必须考虑开发成本与用户成本问题。 - 为什么不用H5?
H5必须在在原生APP上通过浏览器内核运行,与native交互比较弱,一些前端实现起来花时间的UI无法让APP开发去完成——无法最有效地利用前端和客户端的开发时间。要想同时利用好前端和客户端的开发效率,最佳方案还是跨平台开发。写过H5的同学肯定会被它的简单高效、发布即更新、一条URL可适配多端等这些快所吸引,但写过 Native 的同学肯定也会被 Native 的富交互、性能体验、可调用原生能力、可管理内存等特性给我们的业务带来更好的体验。由于和ReactNative一样,都会调用Native端的原生控件,所以在性能上比Hybrid高出一个层次(但比Native弱)。H5页面上长列表(特别是DOM层级比较深,还有操作的话)内存暴增、滚动不流畅、动画/手势体验差等问题。【Weex】 理性思考
(长View性能问题)
- 为什么选用Weex而不是RN或其他如Fluter?
国内RN用的比较多,其次是阿里推崇的Weex。RN支持React.js,Weex同时还支持VUE,VUE符合目前在职人员的技术积累与前端技术发展方向。手淘和天猫曾经尝试过React Native,然后放弃了。React Native的JSX、CSS in JS写法都很别扭,淘宝有很多ISV(即各种店铺),他们之前只会Web技术,写这个有门槛。而且手淘之前有WeApp(用JSON配置原生UI组件来实现动态化的框架)。
RN:Learn Once, Write Everywhere,门槛高一些;多端适配调整,不同平台显示有差异。 - 用单页面而还是多页面?
前端开发人员对单页面开发模式已经比较熟悉,HEADER、FOOTER、js、css一些公共资源可以共用能节约开发时间,在所有的决策只能是时间优先的情况下很容易会去选择SPA。再者,前端熟用的VUE-ROUTER是单页面的路由解决方案,考虑到时间学习成本,也很容易不倾向于选择MPA。单页基于vue-router实现跳转,这种方式还是传统的web开发,能减少很多额外的问题。单页最大的问题,在于你的app就真的成了一个浏览器容器,每次打开都是一个全新的浏览器。多页跳转方式不只是weex-toolkit脚手架应用,也是weex-ui所推荐的,但内层的机制却需要开发者熟悉native的跳转方式,关键这也是开发时必须熟知的。EROS 通过native的navigator跳转,页面之间通过本地存储或者router路径传参数。
事实证明,选择SPA是错误的。 - 为什么程序主体框架结构用VUE而不是native?
如果主体框架是APP,最好是多页面的。(Weex希望主推的模式是整个app使用weex开发(还不完善,需要开发router和生命周期管理)。把weex当作一个iOS/Android组件来使用,类比ImageView,这类需求才是真正的遍布于手淘主链路,涉及到如何让Native同学快速上手“准Web”开发的问题。)
也就是说,主体框架用VUE去搭也是不科学的,泪啊,难过(ಥ﹏ಥ)
四、WEEX踩坑计
(一)、一些必要的了解
Weex 是阿里开源的一款跨平台移动开发工具,Weex 这个名字是取得 weeks 的谐音。
Weex能够完美兼顾性能与动态性,让移动开发者通过简捷的前端语法写出Native级别的性能体验,并支持iOS、安卓、YunOS及Web等多端部署。
对于移动开发者来说,Weex主要解决了频繁发版和多端研发两大痛点,同时解决了前端语言性能差和显示效果受限的问题。
开发者只需要在自己的APP中嵌入Weex的SDK,就可以通过撰写HTML/CSS/JavaScript来开发Native级别的Weex界面。Weex界面的生成码其实就是一段很小的JS,可以像发布网页一样轻松部署在服务端,然后在APP中请求执行。
与现有的开源跨平台移动开放项目如Facebook的React Native和微软的Cordova相比,Weex更加轻量,体积小巧。因为基于web component标准,使得开发更加简洁标准,方便上手。Native组件和API都可以横向扩展,方便根据业务灵活定制。Weex渲染层具备优异的性能表现,能够跨平台实现一致的布局效果和实现。对于前端开发来说,Weex能够实现组件化开发、自动化数据绑定,并拥抱Web标准。
- Weex的上层业务框架有三层:vue2.0,rax,we,如果你用vue2.0来编写上层业务。
Vue 2.x 在 Weex 和 Web 中的差异 - jQuery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:$("lable").val();,它还是依赖DOM元素的值。 Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。
jQuery转Vue项目实践总结 HTML=》jQuery=》VUE - Weex的优势: 依托于vue, 上手简单。可以满足以vue为技术主导的公司给native双端提供简单/少底层交互/热更新需求的页面的需求。
Weex的劣势: 在native端调整样式以及众所周知的生态问题, 维护组没有花太多精力解答社区问题, 官方文档错误太多。
钉钉开放平台、网易严选App感受Weex开发 - 在移动端,动态性问题逐渐成为一个比较棘手的问题。所谓动态性,就是把移动应用本身的灵活性、迭代更新的周期和成本优化到极致。比如淘宝、天猫每次大促的会场页面,要求我们非常灵活的及时调整界面信息和状态,确保在瞬息万变的活动当天紧跟促销节奏,应对各种突发情况。我们不必要为这些动态性在多个端投入重复的精力,更不应该因此而频繁的触发新版本。整个行业迄今为止在移动端的积累都还不足以对产品形态、用户体验、交互方式等细节有完全的前期把握,一个移动应用,客观上需要更多的尝试和探索,甚至是“试错”。
- Alibaba经过一系列的调研、思考和讨论之后,提出了一套完全针对无线电商动态化的技术方案Weex,本意是:
- 致力于移动端;
- 能够充分调度 native 的能力
- 能够充分解决或回避性能瓶颈
- 能够灵活扩展
- 能够多端统一
- 能够优雅“降级”到 HTML5
- 能够保持较低的开发成本
- 能够快速迭代
- 能够轻量实时发布
- 能够融入现有的 native 技术体系
- 能够工程化管理和监控
(二)、上线后让人头痛的白屏现象
1、现象
- X端底部TAB快速切换假死问题,原因是页面未渲染完成(JS加载完成能知道,但什么时候渲染完成不知道),切换到另外一个TAB切换路由需要重新创建一个VUE实例并渲染,出现卡顿,新的实例会出现页面交互的停止,如果点击很多还很快,大概率会崩掉(也有一定概率能运行完并恢复正常)。刚刚新开的X'端采用多页面,每个JS文件相对独立,使用OS原生页面跳转机制,不属于前端跳转,路由跳转动画也是系统自带的,整体体验好很多。
- 后台切到前台,OS内存管理机制会对后台程序进行清理,根据切到后台的时间先后、内存占用情况、优先级等因素进行清理,即使原生页面保留,JS相关的数据会先清理,停留在后台超过30s会大概率清理掉,此时切到前程reload整个页面,避免假死。否则苹果手机上会出现白屏现象(相当于空白网页)。
- 断网情况(404页面)。
- 弱网超时情况。
- 接口报错(SPA问题,一个页面出错,整个JS出错,不重新加载无法恢复)。
- 每次打开通讯录(1500条数据)会新增15MB内存(Android\iOS都是如此)。列表类页面最好通过开发原生页面来解决,基本的固定页面用vue。原生通过适配器加载页面布局,只创建页面可见的视图,滑动时不创建新视图,改变的是视图数据,视图创建的少,占用的内存会少很多。而且可以利用原生的缓存策略。
长view,Memery Leak
2、措施
- 针对情况1
SPA=>MPA - 针对情况2
直接重新reload整个页面,用户感觉与用户刚登陆时或新打开APP一样(无launch),体验较差,应恢复用户数据:
当用户按下HOME键时切到后台长达30s;
从最近应用中选择运行其他的程序时长达30s;
按下电源按键(关闭屏幕显示)屏幕熄灭超过30s;
以上情况30s以内,但页面被回收过的情况。 - 针对情况3、4、5:
断网,标记原因3;
HTTP状态码 4xx、5xx的处理,status=-1,提示网络出错,标记原因4;
HTTP状态码“正常”,但是超过30s没有返回数据,标记原因4(与上一种情况一样,JS区分不出来,状态status=-1),提示网络出错;弱网'bug'
HTTP正常,但数据返回错误码 status!=-1,status!=0,提示网络出错,标记原因5,toast透传msg;
HTTP正常,code=0,但数据不符合预期,空数据导致的空指针一类,weex页面加载任何异常,标记原因6。 - 针对情况6:
通讯录原生化(长View原生化)。
(三)网上总结的坑
- div 无法渲染文本需使用 text 标签
- 不支持富文本,需 native 单独封装 module
- 不支持 z-index,层级靠后优先
- class 表达式需使用数组形式,否则会报错
- css 无法简写(例:padding: 0 0 0 0 不支持,需 padding-left padding-right 各写属性)
- 不支持 dom 操作
- weex 原生滑动事件不支持嵌套 list 和 scroller 标签
- 使用 vue-router 会出现跳转僵硬,如使用跳转动画需单独打包各个 vue 成 jsbundle,用 navigtor 跳转,但单独打包后无法使用 vuex
- 添加 ios 平台后需将 podfile 文件 ATSDK-weex 改为 ATSDK 否则会报错
- gif 图片仅 Ios 支持,android 需单独添加支持库
使用 v-if 会有闪屏现象,推荐使用 opacity 显示(opacity 为 0 时 android 会隐藏层级,但 ios 不会,需做判断) (使用后未发现,可能Weex SDK已经解决了)- weex 全局变量无法在 vue 模板渲染使用,可在 vue 实例中 data 添加
- 不支持百分比,宽度默认 750px
- 图片必须定义高度宽度,否则无法显示
- 长列表分页渲染会出现内存泄漏(Weex称支持超长列表渲染?)
正常情况下,Native memory 业务开发人员是无法处理的,而运行在js core 中的内存,我们知道如果不断开引用,js是无法回收释放内存的。
- weex中的标签只支持官方提供的内部组件,因为那些是会被渲染成native界面的。
- v-bind:class只能使用数组语法
- stream 的 url 选项默认不支持中文,需要将中文转为 UTF-8 来传输。
- 不支持 display:none 即不支持 v-show,需要使用 v-if 来实现显示和隐藏。
- 存储、网络等很多都是异步的,需要注意顺序
- storage 只能存储字符串,取值后再转为json
- weex的stream模块的fetch方法在弱网环境下容易请求失败?使用charles模拟弱网环境,发现在15kb以下的网络下weex有80%的网络超时的概率,而native只有20%的网络超时概率,iOS和android默认不设置超时时间,那么请求的超时时间只有几秒钟(Android是3s),所以在弱网环境下比较容易造成请求超时的情况。weex官方文档对stream的fetch方法的说明,并没有发现特殊的说明。(你在请求数据时,可能会发现官方的文档里没有设置 timeout 这个属性,官方把这个属性值设置为了很短,如3秒,在弱网情况下,这个值是绝对不够的。)
- weex的picker模块在android端存在严重crash和不响应的严重问题,在使用时间选择的界面中经测试发现pick方法在android和iOS都可以正常使用;pickDate只支持iOS,在android直接crash;pickTime只支持iOS,在android直接不响应;
解决方案:如果要使用pickDate,pickTime时间选择方法只能自己定义。 - weex的list控件在少量数据条数下同时上拉和下拉android直接卡住不能滑动,iOS直接悬挂在中间。iOS可以通过写一些代码解决,Android需要改weex源码,只能阿里的人去改。
- weex使用css样式不要这样命名如div,div1,div2,这样做在切换样式时会出现样式混乱的情况
解决方案:不使用1,2,3,这样顺序命名。 - 不允许在Vue中操作style,遍历是很耗性能的
- 开发者数量少,社区活跃度不高,很多问题并不一定能被google搜录到
(四)、其他的问题
- index.js文件较大,超过1MB
加载bundleJS加入缓存机制的优化;
JS大文件压缩(>50%)