转载自:https://mp.weixin.qq.com/s/iHehLneIYibWq6IRjuefxg
早期经历是2010年入行做java服务端和PC客户端,2011年以安卓个人开发者入行。 2012年进入掌阅做阅读器和排版引擎,期间也有机会做了一些电商、金融、智能穿戴方面的项目。2014年加入去哪儿,一直做围绕移动端方面的研发。
背景
去年客户端团队从原生开发栈切 React Native 时想做一个分享,当时正是机票客户端主业务开始切 React Native 初期,有些原生开发者困惑为什么选择逐步放下已经熟悉的技能和经验,去使用 RN 这种较新的甚至 “带坑”的非官方的异构技术作为未来几年的主要技术设施。做这样一个主题是想对团队成员在技能和心理认知上的做前期引导。
原生开发体系的演进
从2010年移动热潮出现至今,回顾这些年来开发体系的演化 还是蛮大的。
首先是小应用时代
大概在 2011 年左右,绝大多数是功能和业务单一的工具 + 游戏类应用。之所以叫小应用时代,因为开发一个应用所需人少(1-3 人),功能单一,业务逻辑少、尺寸小(普遍 1~3MB)。那个时候的应用架构比较简单,像网络、缓存、日志、ORM、事件总线等基础部分封装为库和框架做依赖下沉,其余具体的功能业务交互和逻辑都放到主项目中。
早期的组件化方案 -- 静态组件化架构
到了 2013 年左右开始出现 “航母级”应用,类似像去哪儿旅行、携程、天猫这样的单一 app 里其实承载了 n 多个业务品类,这个阶段稍大一些的应用里每个业务单元背后已经是专门团队开发维护,在业务和功能膨胀、团队拆分业务细化深耕的趋势下之前的单点技术架构在协同性上效率会非常低,于是出现了早期的静态组件化方案,主项目只是一个 launcher 的角色,具体的业务模块是独立的 project,彼此之间使用 aidl/schema/message/eventsbus 等方式互操作。之所以叫 “静态”,是因为各个模块只是开发阶段彼此独立的单元,但在部署、运行时还是把代码和资源搞到了一起。
动态化组件架构有了早期的组件化,接下来希望每个组件都能动态部署更新、加载和卸载,这个阶段涌现了很多像 atlas、qunar spider、small 等开源闭源动态加载技术;动态化组件不仅能做到开发阶段模块隔离,在编译期间和部署阶段也是独立的,运行时按需部署、加载对应的组件。 在这个阶段 Qunar 较早实现了动态化组件技术并完善了运维设施,可以基于组件化技术对各 BU 的安卓组件进行发布热更、回滚运维和以组件为单位的缺陷跟踪统计。
虚拟化容器技术目前主流的动态化组件是需要组件本身按照一定的规则去做特意编写和打包甚至需要修改 aapt 的资源 id 生成规则,容器化技术类似于 Android 版的 Docker,把应用所依赖的系统组件实例 hook 掉,提供一个伪环境。行业可见范围内比较早期的原型是 2015 年 360 手助团队的 DroidPlugin 和和天才少年 Lody 的 Virtual App,后来两位都另起炉灶做了商业化并停止更新开源版本。大家感兴趣在安卓应用市场下载 “闪电盒子”体验。
异构开发方案
做一个 app,除了原生开发以外还有很多其他选择,在移动游戏领域国内几乎没有团队选择用官方的或非跨平台的方式开发。因为这类应用开发复杂度较高且需要频繁更新,11 年左右出现了类似 cocos2d-x、egret 这样的包含跨平台开发框架、地图 / 角色 / 骨骼编辑器等一整套设施的解决方案。在通用研发范畴,虽然没有像游戏开发那样极端,但一个应用中原生代码所占比例已经越来越少,尤其业务驱动型产品中 hybird 已经是半壁江山。
这些异构方案被设计出来是有原因的,他们的共性,一方面是都跨平台,只需开发一套代码稍加适配就能跨不同系统运行,这样能大幅提高业务的交付效率和单位人力产出;二是这些异构开发方案大多是引用了动态语言,天生能够绕过原生开发限制运行时动态加载,自然具备了热部署、热更新、热修复和回滚的能力。
主流的异构开发方案分类
Hybird最早出现的 Hybird 简称 hy,它的原理是利用 android 和 ios 上的 webview,webview 容器提供了执行 html、css 和 js 脚本并完成渲染等完整的 browser 能力,需要原生功能支持就开发原生函数去 port 成 javascript 的 api 调用。 hy 因为在开发协作上比较简单并且背靠海量的生态资源很容易跨平台,至今是最普遍成熟的跨平台方案。但缺点也明显就是加载和执行效率比原生慢,视图和动效过于复杂场景容易出现性能热点,细节像流量消耗、耗电量卡顿这些问题优化空间有限,不同浏览器内核上存在碎片化的适配点。
脚本 +DSL 类
第二类是像 ReactNative、Weex、美团 Picaso、阿里 virtual view(可以看成是这个方向去掉 script 保留 DSL 的简化版)等,脚本执行计算任务,用 DSL 来描述布局样式和对属性事件的绑定,运行时 DSL 在 native 层翻译成 native 组件拼接构造出来,实际的视图渲染和网络 /IO 等都是在 native 层来完成。这类方案和 hy 相比的优点是在开发者具备足够经验和技巧的前提下性能可以无限接近于原生,二是很容易和纯 native 实现的控件无缝集成,rn、weex 这类技术因为实际绘图就是用原生组件,所以可以很容易实现 rn 里套 native,native 里套 rn 这样的特性。即便 rn 中出现性能热点,多数情况都是可以用 native 来辅助解决。
由于早期的定位和设计原因,React Native 的实现是兼容性优先而非性能优先,目前某些场景下还是有一些性能局限,主要是 js 和 native 域的异步互操作延迟略高尤其不适合触控联动这类动效,还有就是渲染层从 flexbox 转换成 android 本身的组件布局这个冗余过程有性能损耗,我们针对 React Native 做了 APM 自动化性能分析设施帮助开发者在早期阶段及时定位发现性能缺陷 ,并且 facebook 官方已经在着手改进 rn 的线程模型和渲染机制,大概会在 18 年底最晚 2019 年出一个比较大的底层重构版大幅提升性能。
独立运行时
这是比较极端的解决方案,比如被微软收购的 xamarin,还有 google 的 flutter,原理是在安卓上绕开 Dalvik/ART,自己搞了一套虚拟机,而且把实际视图渲染(大多基于 skia)也在里面做。优点是容易做成一个统一一致的系统无关的开发模型,理论上性能可以等同甚至超过 Android 原生方案。
对于 iOS,由于苹果大爷的政策原因,在 iOS 上再跑一个虚拟机有被拒审下架封号的风险,所以 xamarin 和 flutter 为 iOS 做了一套 llvm 编译器,能把 c#和 dart 直接编译成机器码,这样只是用非官方语言去写,但编译出来的二进制文件对苹果来说和 oc、swift 编译出来的无异。但这个方式有个短板就是丧失了动态加载能力,不能热部署热更新。
移动端核心技术的变化趋势
如果在 5-10 年前,什么是移动开发,基本就是指开发一个 app,什么是核心技术,一套包括交互控件、网络、存储、MVC/P/VM、事件总线、ORM、日志、图片、缓存等的通用开发架构就是核心技术,但现在因为技术生态本身的积累,很多技术已经通过开源、培训、mooc 下放,技术门槛降低了。 那么现在移动端技术,开发一个 app 已经是一个比较廉价的事情。未来几年移动端技术哪些方向是可以帮助团队和个人建立技术壁垒,我觉得有这些方面。
一个是最开始说到的基于虚拟化容器的动态化方案,这个方案在业内已经能看到非常成熟的产品,只是掌握这些技术的个人和公司现在都没有把成熟的版本开源出来。目前能看到的主要是其 App 叫闪电盒子的公司,还有一个叫做 Virtual App,和闪电盒子类似源码都已经停更转做闭源了,这两个技术主要方案一样都是把 app 所依赖的系统组件用动态代理替换掉,做大量的 hook 替换。 第二类是那些异构开发方案,在通用研发范畴尤其像常规界面和逻辑计算这些,原生开发技术是非常容易被跨平台方案所替换,这个本质上不是团队或个人的选择而是行业的选择。在大趋势下未来 3-5 年如果还要继续做移动端技术,React Native/Weex/Flutter 三个里面从底层到应用至少要精通一个,PWA 可关注。 第三类是垂直领域的技术,比如像图像处理、AR/VR、音视频编解码流媒体、浏览器内核、阅读排版引擎、复杂动效、更高效的 UI 绘制如 litho 等等。在至少一个专项领域去做深做透。 第四类是周边运维 包括对项目的定制化构建、持续集成、性能监控、代码规范审查自动化、自动化测试这些。
泛前端趋势下移动团队和开发者面临的挑战和选择
移动端热潮褪去
早年在大学时候非常热衷微软系技术,从 win32/mfc 到早期的 winform 再到 wpf、silverlight、wcf、ado ef、enterprice libary 大致都搞了一遍。毕业前后一年的实习和工作主要和 PC 客户端、Silverlight 网游有关,起初没对 Android 感冒,11 年那会正直第一波移动热潮,在身边同学的感染下以 “安卓个人开发者”的方式切入这个领域,头一年做了几款小游戏和工具类的 app,通过投放移动广告补贴生活,当时的感觉是虽然开发工具和官方的 api、库、框架相对 .NET 粗糙陈旧且系统的安全性、性能、兼容性问题多,但这样一个免费且开源可定制系统确实命中了手机行业的痛点,尤其借助早期的 MTK 方案大批手机公司绕过 symbian、wince 的授权壁垒快速切入进智能手机市场,Android 终端设备数量的爆发带来了大量移动开发需求,以往 web 和 pc 的需求量快速萎缩。一部分 java/.net 开发者踏着这波市场供需更替的热潮转移到 android 和 iOS 阵地。 2015 年后,一方面移动应用方面的创业增速下降,而且各种开闭源异构技术趋于成熟,通用型研发对原生的需求在持续下降,事实上即便没有 react native 这样的技术,hy 或其他方案也会替换大部分的原生开发。就像以前 java 替代 C/C++,web 替代桌面客户端的过程,不是原生开发不好,而是不可替代性在减弱。 市场需求下降,但从业人员供给没有降低(大家都还年轻,最早一批移动开发者也就 30+ 岁),那么传统的移动开发团队和个人 需要承担的职能和技术输出必定要有所转变。
如何规划未来要做什么,可以从两个角度出发
跟随行业热点趋势,就是那些短期内聚集开发者关注的技术,简单的筛选方式是通过 Github Trending 挖掘。
从公司需求、项目技术痛点出发,比如面对竞品建立垂直技术壁垒,提高业务交付效率,减少版本生效延迟、研发完成即发布、发布即生效、线上问题快速修复回滚,怎么自动化保障代码规范和项目质量等。
转变与坚守
在技能迁移甚至换赛道的过程中转变的是具体的方式方法、语言、库、框架甚至架构,坚守如底层相关的关键性技术,设计模式方法论这些。
大方向选择
在热点趋势成为主流前提前进场做技术储备
找到垂直专项领域,做深打透