框架设计:小程序框架与组件化如何选型定制

著做权归做者全部。商业转载请联系 Scott 得到受权,非商业转载请注明出处[务必保留全文,勿作删减]。

蚂蚁雄兵的年代,人人皆可为王。前端

现在早已经是全民联网年代,能够发现本身的父母大姑大姨等亲戚甚至爷爷奶奶,只要他们在使用千元智能机了,不管是看头条仍是微信仍是抖音,都在参与整个互联网的流量和内容的产生,他/她们经过手机消费了本身的时间,同时为全部的产品提供了更多人物画像的行为数据,不管是上翻下翻仍是留言点赞,每个 APP 都是一个独立的平台,而在这两年,冉冉升起的区别于 APP 的新应用平台,非小程序莫属:vue

上图是从阿拉丁公布的数据报告中截取引用过来的,整个 2018 年,基于小程序生态的融资规模是 80 亿,是 2017 年的整整 8 倍,小程序几乎扎根了全部领域的全部层面,并且除了微信小程序,其余小程序小应用也都在布局:git

在整个泛小程序生态崛起的过程当中,许多创业公司都主动登船,小菜也不例外,咱们是在 2018 年 3 月份开始技术预研和拥抱小程序生态,至此 1 年咱们业务上收获颇丰,而技术这里,也略有积淀,就跟你们分享小程序这块咱们的思考和沉淀。github

用原生仍是用框架

小菜前端的个别同窗,包括我都有过一些开发小程序的经验,没使用任何框架就用小程序原生语法来实现,但小程序的功能都比较简单,因此也天然没遇到太大的工程挑战,而咱们 2018 年要启动的小程序产品具备两个特征:第一个是功能和交互足够的复杂,第二是迭代速度要很是快,两周就要首版上线,以后每周至少发一到两个版本,基于这样的业务背景,咱们也就毅然的选择使用框架而非原生,但这个决策带来的后期风险也的确超出了咱们的预期。面试

若是咱们再回到一年前作选型,估计仍是会选择框架,但至少不会那么乐观的 All in 其中,而是择时机尽早切回原生(虽然咱们目前已经是半原生)。因此给你们的建议是:若是产品功能相对简单,一二十个页面也没有太奇怪的交互和太大的列表数据量,用框架用原生均可以,开发周期短的话就用框架,实际上市面上看到的绝大多数小程序都不属因而复杂应用,用框架都能很好很快的 hold 住,但反过来假如你要实现的产品交互和前端列表数据量较大,图片图表视频多媒体复杂搜索应有尽有,那么能用原生就用原生。redux

如何选择框架

框架的核心价值就是效率,一旦咱们决定使用框架,那么就要把当下及将来市面上可用的小程序框架,作一个必要的比较和选择,这个过程一般会比较纠结。由于截止到 2019 年,还并无一个小程序框架足够足够的好,你们都在六七十分上下,那咱们能够从哪些方面来考虑呢?小程序

小菜前端最初选型框架主要考虑以下几个方面(都很必要但优先级程度自上向下依次下降):微信小程序

  • 框架的成熟程度与开发效率 - 是否知足产品迭代需求
  • 多端(H5/小程序)的兼容程度 - 是否知足产品的端覆盖需求
  • 配置成本/易用性/拓展性 - 是否知足工程师的工程架构需求
  • 总体性能的表现 - 是否能顶得住复杂交互和大数据列表
  • 团队成员的学习成本 - 是否有必要的人员和技术栈储备
  • 框架背后的团队实力 - 是否有足够好的工程实践和开发支持
  • 框架在社区的沉淀和生态 - 是否有群众基础和社区方案
  • 框架是不是 KPI 产品 - 是否会慢慢 Bug 不修弃坑跑路

整体作选型的路子是优先保产品,再看工程质量及合理性,最后看社区及开发者生态健康程度。缓存

很惋惜,即使咱们考虑了这么多,限于当时(2018 年 3~5 月)的小程序框架生态太过早期也太单薄,咱们最终选择了美团的 MPVue(实际上没得选),但上面的参考项今天看来对你们依然是通用的,当时的比对过程我再给你们呈现下,帮你们加深下这个选型运用的过程:微信

首先针对可否优先保产品,也就是框架成熟程度和开发效率,多端兼容程度这块,咱们实际上只有 wepy,MPVue,Taro 可选,针对他们三个,咱们是这样比对的:

  • 社区生态是否足够活跃
  • 跨端迁移成本
  • 框架核心团队是否背靠大厂,是不是 KPI 产物
  • 开发效率问题,更可能是踩坑时间问题

其次,针对工程质量与合理性,也就是框架的配置成本/易用性/拓展性,总体性能这块,咱们是这样评估的:

  • 框架上手成本
  • 底层工程架构基建是否支持到位
  • 性能问题: 先上再说,过得去就好,剩下的就慢慢优化

最后,针对社区/开发者生态,也就是团队成员既有技术栈、社区反馈和生态这块,咱们是这样评估的:

  • 团队成员中是否有人具有相应的技术栈能力
  • 框架是否支持已有的库快速接入
  • 社区对于该框架的反应如何,是否还属于半成品或者存在 Bug 不少的问题

如何作组件化

小菜最初的产品端载体主要是 APP 和 PC Web,尤为是 APP,有 7 个之多,因此 RN 的组件化在 2018 年是有过两个大版本的累计了好几十个,但这个对于小程序来说远水解不了近渴,而小程序的页面数目愈来愈多,组件复用变成了刚需,因此咱们开始了小程序的组件建设之旅。

基于 MPVue 在小程序里写组件,也是比较神伤。由于小程序端代码是静态的(即提早编译好的模版), 因此像 HOC 就没办法用了(还有不少其余一些 Vue 语法糖编译不了), 咱们这里用的都是 mixins,基础的 mixins 有不少:

  • 函数调用相关(去抖/节流)
  • 列表加载相关
  • 用户基础信息/微信信息
  • 数据初始化相关
  • 分享调用相关
  • 页面下拉/滚动相关
  • 收集 Form Id
  • 受权处理相关

基于 mixins 就能够来设计组件了,一旦决定要抽象出一个组件,咱们主要考虑以下因素:

  • UI/功能的耦合程度
  • 内外部调用的耦合程度
  • 组合组件(组件间的通讯层)
  • 组件性质(基础/业务)
  • 兼容问题
  • 后期扩展能力

咱们已经沉淀的组件有:

  • 上传组件(Upload)
  • Tabbar
  • Spinner
  • Radio/Radio Group
  • Video
  • Cell
  • Input/Textarea
  • SearchBar
  • 受权/登陆弹窗 组件
  • 保存/预览图片 组件
  • 图片懒加载/占位 组件
  • 语音录制/播放 组件(Record-bubble/Record-button)
  • 页面异常状态组件 (102/404)
  • 其余业务组件......

这些组件里面:

好比 Input/Textarea 组件,它须要重点考虑 UI/功能的耦合,要如何设计?

  • 组件复杂度高的话,能够切分数据服务层与 UI 层,采用 Mixin 混合抽象方法到 UI 层里。

好比受权/登陆弹窗组件,它须要重点考虑内外部调用的耦合,要如何设计?

  • 组件须要具有单一职责,不能图方便把不少东西都耦合进去
  • 如何和其余组件配合使用

好比 Upload Group 组件,它属因而组合组件,要如何设计?

  • 上传发生异常的处理与上抛。
  • 组合层之间调用的 Hook。
  • 注意 Props 的透传与值的双向绑定。

好比语音录制/播放组件,它须要组件性质,要如何设计?

  • 业务级别的组件,在复杂度高的状况下,也能够考虑切分 UI/数据服务层。
  • 若是通讯层较复杂的话,能够考虑相似 redux 的设计,下层组件 dispatch action 到上层,上层统一管理 action 并 分发数据/事件 给下层组件。

除此之外,组件设计的时候还要兼顾小程序端上与 Vue 的差别性。好比生命周期(组件与页面),在 MPVue 编译完后, Vue 组件生命周期并不会编译成小程序组件的生命周期,说白了就是须要你熟悉两套生命周期:  Vue 组件生命周期与小程序组件/页面生命周期。

  1. MPVue 编译完的 Vue 组件生命周期并不会和 小程序组件生命周期的调用一致,好比第二次点开同一个页面,非页面级别的组件 mounted 永远只会调用一次(除非你在组件或者组件上层挂了 v-if ),而实际上这个组件在小程序里被调用了两次 attached 小程序组件生命周期。
  2. 更不用说 beforeMount/onUnload 的问题了。
  3. 页面数据缓存问题,小程序自己会缓存打开过的页面数据,常见场景就是商品详情页面,第二次打开的时候,在进行页面数据更新以前,页面并非空状态,而是上一次详情的数据。处理的话就有不少种方法了,能够在 beforeMount/onUnload/其余生命周期 里初始化页面数据及置空全部状态,具体就看你怎么设计和抽象了,最主要的目的仍是让开发者尽量少的感知/手动调用。

除了要考虑以上这些问题以外,咱们还须要去解决端上的兼容问题以及框架带来的问题。

微信端的兼容问题简直是层出不穷,不只和机型、系统版本有关,甚至还和微信版本有关。因此当遇到这一类问题的时候,咱们只能求助于 微信开发者社区,期待有相应的解决方案。

框架带来的问题有时候就有点恶心了。好比说 MPVue 并不支持动态的传入 input 的 type 属性,这就致使若是咱们须要文本键盘、数字键盘、带小数点数字键盘等等这一类的 input 时,咱们须要每种类型都写一个 input 组件,平白增长了代码量,而且定位到问题也不方便。

逃不过的原生能力

以上咱们探讨了框架选型和组件化设计,最后再回归到咱们认为很是核心的一个能力,就是小程序的原生开发和优化能力,MPVue 编译完的代码运行时的性能在不少场景里并不达到你的要求,好比输入组件的双向绑定之光标闪烁/内容回退,,大数据量之操做延迟等等...... (没遇到过的同窗自行搜索)。总的来讲就是 MPVue 底层对于数据的操做实现的很稀烂,这个问题也只有当咱们将项目作大了才遇到。

当遇到相似上面这种性能问题的时候,就避免不了去寻找解决方案。但所谓的解决方案颇有限,要么换框架,这时候已经上车,全量换框架工程太过浩大不敢想。要么写原生,写原生不只工程量也浩大,并且原生代码的复用成本也难度不小,这就是框架选型带来的后续维护成本和风险了。

但问题是躲不过去的,终究要解决。除了上面这几点须要去衡量的以外, 还要衡量一些非技术因素:

  • 产品发展形态/可预见的趋势:随着业务的发展以及小程序的权限收缩,为了继续扩大产品的可触达范围,势必会新增更多的端。
  • 用户群体:须要去收集用户的地理信息、手机型号、网络环境等等,综合这些数据去优化相应的点,作到有的放矢。

咱们最终仍是决定当部分组件替换为原生组件,好比:

  • MPVue 写的 input/textarea 在输入的时候就会出现光标闪烁/内容回滚的异常(缘由就不赘述了),因此使用小程序原生语法重写了 input/textarea 组件,主要目的就是让组件的输入可以脱离 MPVue 的更新,直接组件内部走小程序的 setData ,由于当时 MPVue 尚未对数据更新作 diff 操做,目前听说作了一层 diff (实际效果你们本身去测评吧)
  • 产品中的文章详情须要 Markdown 渲染,由于文章内容相对来讲都是数据量比较大的,使用 MPVue 去对这部分数据进行解析的话性能会相对来讲较差。所以咱们也使用了原生去实现了一个 Markdown 渲染的组件。

其实除了将组件替换为原生组件以外,咱们还能够去优化原生的 setData 方法,具体内容能够阅读 westore 这个库,进一步提高性能。

最终,咱们的架构慢慢就会变成了这样:Vue 会慢慢成为一个数据注入/数据分析/事件分发三者集合的中心枢纽同样的存在,底层是由各类高性能的原生组件,上层是由 Vue 来分发事件给不一样组件,注入数据到不一样组件里,收集埋点行为/事件。

这样一个现状依然有它新的问题,首先是多端复用成本低,如今还没法一套代码在 H5/小程序里所有通用,其次是小程序原生学习成本仍是比框架要高,这对于不熟悉原生的同窗都是一个不小的技术学习成本。

当下的困境

当下来看,咱们以前选择的 MPVue 已经不能很好地支撑业务需求了。其一是由于 Vue 与咱们的主体技术栈的分割,二来 MPVue 并不能支持跨多个平台开发。

跨多平台开发已是当下的一个迫切需求。假如一个需求须要维护多端的代码,那么势必会须要更多的前端资源投入,这个成本是难以接受的。所以咱们也开始考虑究竟是使用市面上相似 Taro 这样的框架仍是选择自研,二者的选择都有各自的好处。选择 Taro 这样的框架可以让咱们迅速进入开发,可是长远来看免不了可能会出现 MPVue 相似的维护问题;选择自研的话虽然不会存在维护上的问题,可是会短时间内须要投入更多的前端资源。

以上这些问题就是咱们当下遇到的一个困境,选择任何一个方案均可能对未来形成巨大的问题,就好比当初咱们选择 MPVue 那样。

Scott 近两年不管是面试仍是线下线上的技术分享,遇到许许多多前端同窗,因为团队缘由,我的缘由,职业成长,技术方向,甚至家庭等等缘由,在理想国与现实之间,在放弃与坚守之间,摇摆不停,心酸硬扛,你们能够找我聊聊南聊聊北,对工程师的宿命有更多的了解,有更多的看见与听见,Scott 微信: codingdream,也能够来 关注 Scott 跟进个人动态

2.png
1.png

相关文章
相关标签/搜索