腾小云导读
PC Web 端、手机 H5 端、小程序端、App 安卓端、App iOS 端......在多端时代,一个应用往往需要支持多端。若每个端都独立开发一套系统来支持,将消耗巨大的人力和经费!腾讯视频团队想到一个“偷懒”的方法——能不能只开发一套基础系统,通过兼容不同平台的特性,来快速编译出不同平台的应用呢?本篇特邀腾讯视频团队为你分享快速编译出支持多端的应用、一套代码行走天下的“偷懒”历程。欢迎阅读。
目录
1 背景
2 设计思路
3 具体实现
4 总结
01、 背景
腾讯视频搜索在多个端都存在:安卓 App 端搜索、iOS App 端搜索、H5 端搜索、小程序端搜索、PC Web 端、PC 客户端搜索。每个端,除了个别模块的样式有细微差异之外,其他都一样,如下面的图片所示。
按照以前的现状,安卓 App 端搜索一套代码、iOS App 端搜索一套代码、手机 H5 端一套代码、小程序端搜索一套代码、PC 客户端一套代码、PC Web 端一套代码......每套代码都是独立开发,独立维护,成本非常高。并且,后端的搜索接口以前也是分散在多个不同的协议中,有的平台是 jce 协议的接口,有的是 PB 协议的接口,也是五花八门。
随着业务增长的需求,我们已经没有足够的时间来维护各自一套独立的系统,我们打算进行升级改革!治理的办法就是:收敛!把后端不同平台的接口都归一到同一个接口中,通过平台号来区分;前端也将不同平台的代码,收敛归一成一套代码,通过条件编译来兼容适配不同平台的差异性,不同的平台,在蓝盾流水线中配置不同的参数来上线,从而达到多合一的效果。
总体来说,我们团队就实现一个“多端合一的万能模板”的想法达成一致。并且,我们希望使用 hippy-vue 技术栈。
理由有以下:
Hippy 是公司级别的中台框架,有专门的团队在进行问题的修复和功能的迭代开发,并且广泛应用到了很多公司级的应用中,暂时不会出现“荒芜丢弃”的局面; Hippy 是为了抹平 iOS、Android 双端差异,提供接近 Web 的开发体验而生,在上层支持了 React 和 Vue 两套界面框架,前端开发人员可以通过它,将前端代码转换为终端的原生指令,进行原生终端 App 开发; Hippy 在底层进行了大量的优化,使利用 Hippy 框架开发的终端 App 应用,在启动速度,可复用列表组件、渲染效率、动画速度、网络通信等方面都提供了业内顶尖的性能表现,值得信赖; Hippy 在上层支持 Vue 技术栈,正好我们团队目前所有的前端项目也都统一为 Vue 技术栈,开发人员上手毫无违和感。 |
---|
02、设计思路
系统的架构图如下所示:
通用模版为了简化开发、提高开发效率,在模版中集成了大量现有组件和工具包,具体可以分为以下三层:
- 第三方工具层
在通用工具库中,模版包装并提供了很多常用方法,比如 cookie 的设置和 cookie 的获取方法;DOM 的操作方法;Cache 的设置,Cache 的获取,Cache 的过期时间等。在第三方接入库中,模版已经接好了 Aegis 监控,Tab 实验的实验值获取,大同上报等;在打包编译库中,模版提供了通用的 Hippy App 打包安卓脚本和 IOS 脚本、H5 的打包脚本、小程序地打包脚本、一套代码,运行不同的打包命令,执行不同的编译打包脚本,就可以生成不同平台对应的发布包。编译打包在后续还会详细讲解。
- 数据管理层
在这层中,模版集成了跟数据处理相关的模块。
在 Store 层,由于该模块是基于 Vue2 实现的(Vue3 会在下一个版本中提供),模版已经集成好了 Vuex、State、Getters、Mutations、Actions 等,并且都有实例代码(该模版是基于 Vue2 实现的,Vue3 会在下一个版本中提供);
在 Model 层,模版提供了一套将 PB 文件转化为 TS 类文件的方法,方便快速接入后端PB协议接口请求;同时,还包装了接口通用请求方法,以及全局的统一错误处理上报方法;在数据配置中,模版提供了全局的常量配置文件,应用的版本配置文件(版本的配置对 Hippy App 的应用非常实用),以及 UI 样式的配置(正常模式样式还是暗黑模式样式,宽屏,窄屏等)。
- UI 层
为了提高开发速度,提高开发效率,模版提供了示例页面代码。同时,根据脚手架来选择是否需要路由,来动态添加应用的路由;以及常用的基础组件库。这些组件库中的组件,是从众多 Hippy 应用中提取出来,实用又高效。
03、具体实现
本文将从 Hippy App 端实现,Hippy H5 端的实现和 Hippy 微信小程序端端实现来分别展开介绍。
下图是 Hippy App 端实现逻辑。
App 端的入口文件为 main-native.ts。在里面,声明了一个 App 实例,指定 phone 下的一些属性设置,比如状态栏、背景色等等。同时,需要用到的 native 组件,都需要在 main-native 中进行声明绑定,才可以在页面中使用。
例如:下图示例中注册声明了两个 native 组件,LottieView 和 VideoView,在页面中就可以直接使用这两个 native 组件。
Vue.registerElement('LottieView');
Vue.registerElement('VideoView', {
component: {
name: 'VideoView',
processEventData(event: any, nativeEventName: string, nativeEventParams: any) {
// To do something for the native component event
return event;
},
},});
main-native 中还有一个重要的方法:app.$start() 方法。
该方法为 Hippy 引擎初始化完成后回调到 Hippy 前端的方法;Hippy 端跟 App 方法进行通信,通过 jsbridge 来进行,模版中已经封装好了具体方法;Hippy 请求后端接口,通过 fetch 协议,也有具体的协议方法封装;Hippy 在 App 内部的跳转,是通过伪协议跳转来实现的。
Hippy App 应用的部署分为以下三种情况:
- 本地调试
本地调试是通过 Hippy + Chrome Devtools 来完成,通过 WS 通道转发消息,具体流程如下图。
- 部署测试环境
模版中引入了环境变量参数,同时在代码模版中做了大量环境变量的兼容逻辑,比如测试环境用测试环境的接口,正式环境用正式环境的接口;测试环境用测试环境的 CDN,静态文件上传到测试环境,测试环境部署测试环境的离线包等;测试环境的调试我们是通过离线包的方式来实现的,有专门的测试环境流水线接入使用,只需要稍微做少许调整即可,有需要的可以私聊。
- 部署正式环境
正式环境流程会做这样几件事情:正式环境接口、正式环境的 CDN、正式环境的日志上、部署正式环境的离线包平台、图片的特殊处理。因为 App 端是采用离线包的形式,如果所有本地图片都打包到离线包中,会导致离线包包体积很大,会影响到 App 的整体体积大小和离线包的下载速度。模版中做了针对图片的特殊脚本处理:引入了图片编译大小变量:STATIC_SIZE_LIMIT。当大于该限制条件的图片都一律上传到 CDN,如果想保留的,则需要增加特殊声明:inline。
具体流程如下图所示:
Hippy H5 的实现流程如下图所示。
Hippy H5 的实现跟 App 的实现流程类似,但是差异如下:
App 的入口文件为 main-native.ts,h5 的入口文件为 main.ts 文件。H5 的入口文件中,没有关于 iphone 的设置,跟 Web 的设置一样;H5 的路由用 vue-router,页面中的路由跳转都是 H5 超链接,不是伪协议;H5 的本地调试很简单,跟 Vue Web 一样,都是在本地起 http-server 来测试;测试环境的部署和正式环境的部署都是采用的服务器来部署,不是离线包。 |
---|
这里重点讨论一下大同上报的实现。大同上报在 App 端的上报参数声明跟 H5 端的上报参数声明不一致,如何统一这些差异?模版中的解决方案是:封装自定义标签 Directive。
具体实现如下:在 Directive 标签中兼容 App 和 H5 的不一致。
/**
* @example
*
* <element v-report="elementReportInfo" />
* <element v-report="{ eid, ...extra }" />
* <page v-report="{ pgid, ...extra }" />
* <page v-report.page="assertPageReport" />
*/
Vue.directive('report', {
bind(el) {
el.addEventListener('layout', throttledForceReport);
},
unbind(el) {
el.removeEventListener('layout', throttledForceReport);
},
inserted: setReport,
update: setReport,
} as DirectiveOptions);
很多人可能会问,Hippy App 跟 Hippy H5 有很多不同的地方,如果写两套代码,会不会导致代码的体积变得很大?答案是一定的,为了解决以上问题,该万能模版提供了条件编译。引入环境变量:isNative。然后,根据该条件,进行条件编译,不同的平台,生成不同平台的代码,避免了生成大量冗余代码。
Hippy 微信小程序的实现流程如下图所示:
小程序的实现是基于 Taro Vue 框架。该框架跟 Hippy Vue 框架天然兼容,但是也有一些小程序的特殊地方:
小程序的入口文件约定为 app.ts,创建 app 实例是在 app.ts 中来完成;小程序的主页面文件为 app.vue,在其中定义小程序的状态栏,标题栏,页面等;小程序的全局配置在 app.config.ts 中;小程序的构建脚本在 script 中的 index.js。小程序的代码是基于 Hippy Vue 的代码通过 Taro 自动构建转化而成,很多配置都是自动生成的,只需要在开发的时候,遵循约定的命名规范即可。 |
---|
为了一套代码能够同时支持 App,H5 和微信小程序,需要遵循一些约定的规范,否则在从 Hippy Vue 转化为 Taro Vue 的时候会遇到一些问题:
文件夹命名规范:全部小写加“-”, 例如:node-redis, agent-base 等,不要用大驼峰等;文件的命名规范:跟文件夹命名规范一致,全部小写加“-”,例如:eslint-recomment.js;属性的命名:也采用小写加“-”, 例如:data-url。 |
---|
04、总结
目前该模版已经在腾讯视频的搜索场景落地,并且上线应用,但是,还是有一些需要共同打磨的地方:
Vue3 的支持:目前我们是基于 Hippy Vue2 来实现的。随着 Vue3 的广泛应用,后续我们需要升级到 Vue3。
组件丰富:通用组件的种类还不是特别丰富,只是基于我们腾讯视频搜索场景进行的封装,后续可以补充更多更丰富的组件。
迭代升级:通用组件目前还是通过源代码的方式存放在代码模版中,不利于后续组件的升级迭代。计划后续会把组件给迁移到我们的应用组件库平台 Athena,该平台我们会后续发专文介绍,大家敬请期待。
以上是本次分享全部内容,如果觉得文章还不错的话欢迎分享~
-End-
原创作者|熊才刚
技术责编|陈恕胜
你有什么开发提效小技巧?欢迎在腾讯云开发者公众号评论区中分享你的经验和看法。我们将选取1则最有意义的分享,送出腾讯云开发者-文化衫1件(见下图)。6月21日中午12点开奖。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。