本期内容分为5个部分:
-
背景
-
工程能力
-
稳定性
-
效率提升
-
总结
背景
引言
现代社会生活节奏不断的加快,时间也越发的碎片化。三分钟的朋友圈,五分钟的抖音,十分钟的王者荣耀……这种碎片化的时间带来的仅仅是焦虑、浮躁、注意力不集中。
随着公司业务迭代速度加快,工程碎片化严重程度加深,直接导致后期业务开发成本越来越沉重。
另一方面,随着 App 月活不断提高,团队结构不断升级、需求量不断增加,工程容错率不断下降,崩溃率在不断攀升,对 App 稳定性存在着极大的挑战。如图所示:
因此,工程治理对后续 App 的发展起到关键性作用。下面将通过工程、稳定性、效率三个维度,阐述玩物得志 App 工程的治理过程。
工程能力
云端配置中心
现状
-
配置开关零散分布在各个不同的服务端接口,导致客户端人员调试配置困难重重。
-
修改配置完全依赖于服务端人员,导致客户端人员略显被动。
支持特性
-
及时性:配置数据实时更新(包括运行态)做到云端配置既本地配置。具体做法可见下方~!
-
流量控制能力:实现类A/B Test的方案。
-
增量下发能力:配置中心根据客户端版本号来判断返回的配置。
-
可视化配置中心:提高容错性,增强可调试性。
及时性实现思路
所有请求接口响应头增加配置中心版本号,若感知本地版本号与服务端版本号存在差异,即请求配置接口刷新数据。
为了保持数据及时性通过直链通道push是最优解,目前公司直链通道还在建设之中,这种背景下通过请求响应到头对配置中心的增量下放是现阶段比较合适的方案,事实证明这种方案对性能造成的影响是微乎其微的。
效果
-
收拢各个配置,降低服务端的开发成本。
-
客户端同学可以自主进行线上开关控制,大幅度降低客户端配置对服务端的依赖程度。
-
配置内容规范化管理。
App 动态化
赋能业务,释放业务开发资源。以玩物得志分享需求为例:不同业务场景的分享平台与界面展示都可能存在不统一的现象,这种业务存在大量的场景导致业务的复杂度变得非常高。如图所示:
动态化框架预研
团队选择使用 Weex 来实现工程动态化能力。
因上手难度低稳定性较高,比较适合玩物得志 App 现阶段状态。
多端通信设计 效果
业务在需求节奏不变的情况下,人力投入减少一半,对缓解业务研发压力起到了明显作用,同时应用的整体性能和稳定性与 Native 基本持平。
网关标准化
在不影响原有网关的基础上,从功能层面和业务痛点入手赋能业务,做到业务请求只专注于业务本身。
功能层面
- 标准化请求头、出入参、签名、拦截器、解析等一系列功能,避免出现多套标准浪费开发资源的情况,为后续其它衍生 App 网关标准化打下基础。
业务层面
- 开发无需增加任何业务以外的功能,比如自动生命周期释放、弹窗、判空、成功 / 失败判断、崩溃,减少大量不必要代码,增强工程稳定性。
业务通信
路由标准化
这项工作对将来工程大前端化进程的演进起到至关重要的作用。
-
定义路由规则任何业务页面都有一个唯一路由。短链完全按业务模块划分不可更改。如 “/group/path” 。
-
拓展路由能力通过多重(白名单、来源、开关)安全校验,形成一条安全调用链路保证路由安全调转。
-
降级方案当某个路由所在页面出现异常时,支持重定向到另一个配置页面。
跨工程方法调用中间件
定义
不同工程间方法调用的能力。
原理
将一个工程拆分为实现层与接口层,工程直接依赖转变为接口层间接依赖,编译时通过一定能力对工程实现与接口进行映射绑定,以实现工程间调用能力。
这样的做法可以理解为C++ 工程中 .cpp 与 .h 的关系。
利用 git submodule 管理每个工程的接口层,可以使工程间协作更加高效喔!
事件通信
-
制作类似 EventBus 的事件处理/管理中心。
-
制定事件规范,解决事件定义乱象的局面。
稳定性
工程治理
为多图多视频的 App 提供解决问题思路。
动画治理
调研Lottie、SVGA 动画库:
选取方案:Lottie,以 iPhone6s 为例:
图片治理
图片占用大量 App 内存,导致 App 越来越卡,严重影响用户体验。
基于这样的背景,我们做了下述优化:
- 标签化图片链接:对图片链接进行统一拦截与识别,并根据标签的不同做不同的优化处理,比如是否直接压缩处理。
依赖于SDWebImage和CDN图片服务,使用Hook原理加载URL层的调用,针对URL追加图片服务需要的策略参数,例如:图片大小、图片质量、裁剪策略等参数。
-
网络图片自适应:服务端智能裁剪返回适用于当前手机尺寸的图片,合理化内存占用。
-
接入CDN:加速图片网络请求。
-
列表图片预加载。
列表预加载
无感加载列表内容,提高用户体验。
思路
- 在当前列表视图展示到一定比率时预加载后续所需数据。
- 将全局列表刷新切换为局部刷新。
UITableView的分页加载的代码对比
UICollectionView的分页加载的代码对比
成效
-
数据加载完全前置,用户对刷新阶段完全无感,大幅度提升用户体验。
-
局部刷新提升 50% 渲染性能。
治理效果
包大小治理
-
服务化图片压缩:统一处理图片压缩(包括图片大小压缩与 WebP 格式转换),释放开发者需要关心图片大小文件的问题。
-
Android 动态加载 so 文件:利用特殊方法远程依赖so,通过完全释放 so 包的占用空间来达到缩减包大小的目的。
需考虑 Android 兼容性
效果:包大小下降 30%(不同工程下降比例不同)
H5 优化
WebView 预加载
原理
提前装载特定标记 H5 地址对应的 JS 环境,并缓存该页面 JS 环境。当跳转页面时,取出已预加载过的 H5 页面环境, 同时开始执行业务逻辑和渲染界面。
效果
减少页面加载的时间,大幅提高页面加载速度。
其他
-
接入 X5 内核,加速 H5 渲染
-
手势交互统一
安全气垫中间件
概述
为 App 提供安全保障,提升用户体验的一项能力。
原理
对崩溃进行实时监听,一旦检测到崩溃将用户进程进入恢复进程,进而运行恢复服务。恢复服务中夹杂一系列判断,这些判断可进行热修复请求、清空缓存、触发新版本升级等一系列的操作,依赖这些操作来确保 App 运行环境的稳定。
效果
以 iOS 为例, 安全气垫有效防护代码潜在风险导致的 App 崩溃。
Android & iOS 升级能力
作用
- 验证新版本是否有重大 bug 或者严重影响用户体验的问题
方式
-
强制更新
-
建议更新
-
灰度发包
以 iOS 为例:
Android 热修复
-
多维度热修复能力(单渠道、系统版本、手机版本、用户id等)
-
一键式补丁包制作能力:定制发包工具简化繁琐的补丁包发布流程,保障补丁包的正确性
-
基准包自动私有化存储:云端自动存储能力
-
热修复灰度能力
-
Jenkins打包:保障编译环境统一
MainDex方法数监控防止超标:接入热修复后方法数容易超标(65536),这块需要做好严格控制。
效率提升
调试工具
经过一系列调研,选择在 DoKit 开源的基础上进行功能修改 / 工程适配,以提升开发调试效率。
优势
-
可定制性
-
开源性:让工程的适配兼容更具针对性。
-
开发痛点全覆盖,凡是开发测试需要的调试能力一概俱全。弱网模拟、DB浏览、性能监控、View层级查看等。
效果
- 效率痛点全覆盖:举配置中心权限全收拢导致多方串行开发场景的例子。
如果开发需要调试切换配置,则需要让权限拥有者切换权限,这样做会让一方阻塞引起多方阻塞,影响开发效率。如果借用上方工具可以做到定制一层配置的拦截,从而使多方串行变成多方并行,多方并行的效率显而易见。
-
提高开发/测试性能验收的效率:利用工具内的性能监控工具,直观的查看当前性能情况。
-
调试能力增强
编译耗时
被评为最困扰业务开发的问题,提供几个可供参考的方向:
-
选择最优 Gradle 版本与编译参数。
-
Buck &OkBuck:Facebook & Uber的快速编译构建方案(依赖下载慢、侵入性强)。
-
Apply Changes & Intants Run:官方加速编译能力(不一定能适用于所有工程)。
-
Freeline:号称可以实现秒级编译,不过目前已不更新未详细校验可用性。
总结
玩物得志 App 本着 “让业务更聚焦,让工程更轻量,让体验更顺畅” 的宗旨,围绕 App 工程能力、质量、效能三个方向,根据组合进化的思想(技术来自此前已有技术的新组合)以达到投入产出比最大化的目的。
最后,奉上 App 架构演进图:
能猜到后续 App 工程会做什么改进吗?