本文来自于2019年4月20日在小打卡公司举办的“小程序的技术实战交流”的技术分享
点击查看:小打卡 | 如何基于微信原生构建应用级小程序底层架构(下)
大家好,我是小打卡的前端负责人金轩正,今天分享的主题是如何基于微信原生构建应用级小程序底层架构,这个命题看上去好像有些大,不过不要紧,这次分享我把它拆一下,大致从
- 小程序原生开发面临的问题
- 小打卡整体架构演进
- 开发中摸索与实践
这三个方面来看这个讲一下
小程序原生开发面临的问题
ok,首先第一个方面原生开发遇到的问题
小程序从17年诞生2年来一直处于互联网风口,不过对于开发者而言的整个开发体验不是特别友好,在17-18年之间我和很多开发小程序的小伙伴们聊过,大多数的反馈可能分为下面大致几类,当然还有更多:
- 没有父类,无法使用继承挂载全局方法,扩展生命周期没有父类,无法使用继承挂载全局方法,扩展生命周期
- 不支持跨页面/多页面通讯
- setData的性能瓶颈
- 代码包大小限制 1/2/4/8 M,没有npm包
- 代码发布流程繁琐
其根本原因是将刚刚诞生的小程序与已经非常成熟的React,vue,angular作对比,而没有将小程序作为一个新的生态来看待,当然这个是一种看待事物的进步,并不是倒退,我在这里说这句话的意思是有更多的问题需要我们开发者主动去解决问题,推动整个生态的前进与发展
其实这里可能有些朋友会问,已经有很多优秀的框架已经解决了这些问题,那么为什么还要使用原生开发?
确实在这段时间内出现了很多优秀的解决方案,我们不用并不是因为情怀哈(当然还是有那么一丢丢)
更多的是下面几点:
历史包袱,改造成本过高
小打卡在小程序刚出现的时候就进入开发了,当时框架还不成熟,而且对创业公司来说时间和迭代效率高于一切,在人手不足,业务模式尚未形成,还处于探索阶段的情况下花费大量时间去做对产品影响较小, 甚至delay迭代速度事情不是很赚
减少与第三方沟通成本
高速迭代的情况下,将时间尽可能的覆盖于业务上,避免在整个开发-上线闭环上增加节点
避免开发黑盒,控制风险
虽然整个社区是非常活跃的,fixed一个问题同样是需要花费一定时间,但是很多时候需求是不会等你bug fixed
如非必要,勿增实体
即“简单有效原理”,这句话还是我去年刚来公司的时候和阿赖聊他所说过的
放在项目开发上我的理解是在架构层面要做的尽可能的薄,避免过度设计
这样才有足够的扩展性,灵活性,容错性
这些框架虽好,但是对我们当前业务来说可能过于复杂,比如跨端在之前的阶段还没有这方面需求,而像组件化小程序已经支持,自动化构建我们自己也是可以搭建的并不复杂
相信微信小程序团队
是真正的想把这件事情做好,而且做的是一个生态,不论是小程序对于反馈响应速度,和迭代速度非常给力,还是对开发者社区运营,比如是社区活跃与审核速度挂钩,社区周刊,优质个人和优质企业
对齐web标准,并且更加开放
小打卡整体架构演进
其实小打卡整个架构并非一蹴而就的,就像前面所说的如非必要,勿增实体,而是大量的实际开发中遇到的共同问题解决方案的集合题
常规架构
这个是微信小程序给出的快速开发模版的一个开发模式:
server模块提供数据,App作为全局对象直连所有的业务模块,工具函数提供api处理业务模块的需求
优点:
- 整个模型非常简单,上手快,学习成本
- 低结构清晰,在业务不复杂的情况下可以快速开发
不瞒大家其实小打卡在最初的半年内基本都是这套模式。
当然是在业务不复杂的情况下,复杂情况下会出现哪些问题呢?
- App作为全局对象在有大量业务模块连接的情况下,代码很容易膨胀,在多人开发的时候问题非常明显,无论是fixed bug还是正常的业务开发都会造成麻烦
- 页面之间独立,缺少公共模块,唯一的工具函数又要尽可能保持单一职责来提供服务(小打卡当时就是因为这个问题导致很多工具函数内部存储直接修改外部状态,导致大量强耦函数合无法拆分)
- 业务层直连server层,未拆分数据层的情况下,基本不存在复用性
上面所述的问题,从我接手这个项目到真正的调整持续了挺长一段时间,主要是缺乏一个契机来进行优化
优化的转折点
然后突然有一天产品同学跑过来说:
我们要有自己的核心数据仓库,我们要看实时数据
ok,涉及到数据采集的问题了,我这边从浅到深大概列了几项:
- 最基础的多个页面pv,uv如何监控,不可能每个页面都要手动收集
- 为了统计页面和事件的分享和回流的数据,需要在分享事件携带大量的参数
- 微信的wx.previewImage, wx.chooseImage 等api对于用户session的收集造成很大麻烦
我们先解决第一个问题,如何收集页面pv,uv
容易陷入的误区
在解决问题之前,我们先说一下开发小程序容易进入的误区
- App 和 Page 等函数工厂是微信原生提供,不可修改
- 小程序项目结构是基于App, Page, 工具函数三个模块构建的
- 小程序的全局存储只有globalData和本地缓存
其实产生这些误区最根本的原因是小程序没有提供在复杂业务逻辑下的开发范式,比如vue,react有自己的通用开发模版
如果保持这些观念来进行开发的话,很容易将路子走窄,并且难以解决一些实际上的问题,
其实不论小程序和传统web有多少不同,
本质上还是在js环境下开发
小打卡架构图解
为了更好的方便理解后面的具体实现,我提前放了一张目前小打卡的架构图
- 首先很熟悉的server这一边垫了一个数据层,主要将数据层和业务层解耦,提高复用性,并且提供一些通用功能,比如返回格式化数据问题,参数校验,日志监控…
- 在App对象和业务层同样增加了一个全局模块,提供独立于业务和工具类,只提供api之间双向通讯的渠道
- 工具模块的话其实就是对业务层的增强,比如常见的请求模块,上传模块,路由拦截等等
- 业务模块的话基本除了增加Component和中间层外没有太大变化
这个图上可能有两块可能大家觉得比较怪异,一个是global里面的函数重载,还有一个是业务模块的中间层是什么?
函数重载其实就是修改微信提供的App, Page, Component函数,使其更符合我们的业务场景,
业务模块的中间层就是依赖于函数重载的扩展
其实小打卡的整套架构都是基于这两个模块,这两个模块赋予了更多的可能性,然而实现却十分的简单