17666030540

网站建设 APP开发 小程序

KNOWLEDGE/知识

分享你我感悟

您当前位置>主页 > 知识 > 小程序 >

小程序时代:如何跨多小程序开发协作?

发表时间:2020-06-02 18:36

文章来源:快明科技

浏览次数:


导语

小程序端越来越多,跨平台开发框架逐渐成为开发小程序的主流目前跨平台开发有较多的开源解决方案,本文介绍一种简单而有效的方法,解决复杂小程序的跨团队开发协作,希望对你有所帮助。


背景

目前市面上小程序端越来越多,跨平台开发框架逐渐成为开发小程序的主流。目前跨平台开发有较多的开源解决方案,比如美团点评的mpvue、滴滴的Chameleon、凹凸实验室的Taro等,都做得比较好。这些框架帮我们解决了一处开发,多处运行的难点。但是在复杂的业务场景中,最终落地也存在着许多困难,需要自己解决。以58房产的新房业务小程序为例,实际的业务场景中,既需要有独立承载功能的“58同城新房楼盘精选”小程序,也有依托于其他流量平台的入口,比如在“58同城”、“安居客买房”等都有相应的新房业务,同时还有交叉的业务场景,比如在同经纪人业务结合的“安居客经纪人网店”中展示新房楼盘。这其中既有微信小程序,也有百度小程序。

这些业务有较多的共同点,比如基础功能逻辑是一致的,但是也存在很多差异性,比如商业逻辑,页面皮肤以及一些差异功能点。





新房首页对比

上图为三个小程序的首页对比,可以看到独立的小程序“58同城新房楼盘精选”集成了账号、城市、消息,在“58同城”和“安居客买房”这些能力则是依赖主体小程序。另外三个小程序之间还有些细微差别,但是楼盘相关的基础功能确是相同的。


一处开发多处运行的难题

作为业务方,我们希望业务代码也可以一处开发,到处运行。方案设计之时,我们的目标便是业务代码在同一仓库管理,同时方案具备较大的灵活性以适配各种环境。

在上述的背景下,实际开发中会遇到如下困难:

a) 各个小程序归属的开发团队不一样,使用的开发方案也不一样,有原生开发、wepy、Taro、mpvue等,意味着在源码层面是难以进行协作开发的;

b) 业务方与平台方之间是跨团队协作,需要尽量减少耦合,提高协作效率,同时避免相互影响;

c) 需要具备在各个小程序环境中的差异化开发方案;

d) 所有业务代码同一地方管理,意味着会有不必要的代码,需要有机制保障最终的打包结果大小是最优的;

e) 在不同平台小程序中,会依赖他们各自提供的基础能力,比如账户体系,消息等,这部分在各平台小程序中也存在着一定差异性;

f) 在不同场景下需要具备不同的接入方案,支持微信插件方式接入平台小程序,也要支持业务分包方式接入平台小程序。


整体架构设计

本方案基于Taro 1.3版本实现,其他小程序框架也可使用相同的方法做改造。在现有Taro基础上,无法支持到一份源码打包成多个同类型的小程序,因此在现有配置层进行扩展处理,并添加适配层,对于各个小程序不同点进行处理,最终实现直接打包到多个不同的小程序中,整体的架构主要分为四层: 

a) 配置层,用于解决在不同场景下的差异化,包括环境变量、主题样式、页面配置等;

b) 源码层,为具体的业务代码,常见方案,不做具体介绍;

c) 适配层,用于对接不同方案下小程序提供的接口,并牟平不同小程序提供的接口差异,为源码层提供统一的接口;

d) 打包层,与配置层相结合,用于打包最终交付结果;

以新房为例的架构图:






1.  配置层处理

  1) 打包脚本配置

若要支持多小程序开发,需在package.json中增加scripts,用于区分环境。这里我们用的是cross-env这个包来设置,比如在打包58同城小程序时,加入环境变量WEAPPSOURCE=wbweapp。

{ "build:weapp": "taro build --type weapp", "build:wbweapp": "cross-env WEAPPSOURCE=wbweapp taro build --type weapp", "dev:wbweapp": "cross-env WEAPPSOURCE=wbweapp npm run build:weapp -- --watch",}

然后在`config/index.js`配置defineConstants,用来配置一些编译时的全局变量供代码中使用,这里的配置会用于做打包的差异化处理。大部分的差异化配置,我们都放到了编译时来进行配置,有助于降低代码打包后的大小。其原理是通过webpack的define-plugin和uglifyjs-webpack-plugin两个插件配合来删除掉不可达代码,保证不使用的代码不会被打包。

config.defineConstants = { WEAPPSOURCE: JSON.stringify(process.env.WEAPPSOURCE), WBWEAPP: '"wbweapp"', AJKWEAPP: '"ajkweapp"',}


   2) 差异性样式处理

在现有业务中,需要同时支持58同城和安居客两个品牌。二者之间页面结构是一致的,但各自有些主题色,我们将这部分差异抽取出来,变成Sass变量,然后整合至一个scss文件中,通过编译时引入不同的scss文件,来达到切换主题的作用。这里主要是配置`config/index.js`中的`config.plugins.sass.resource` 。

const sassConfig = { wbweapp: '../wbweapp.scss', ajkweapp: '../ajkweapp.scss'}config.plugins.sass.resource = path.resolve(__dirname, sassConfig[process.env.WEAPPSOURCE])


    3)差异化页面处理

源码层中会包含所有场景下的全量页面,但每个场景所需的页面只是其中的一部分,需要做差异化处理。处理方法同上,略有差异点,通过编译打包时pages的配置不同,在`app.tsx`中的pages是决定引入哪些页面,我们通过传入环境变量找到对应的配置页面,实现按需配置打包。

`config/index.js`中配置:

const pagesConfig = { wbweapp: ['pages/a'], ajkweapp: ['pages/b']}config.defineConstants = { PAGES: JSON.stringify(pagesConfig[process.env.WEAPPSOURCE])}

`app.tsx`中配置:

class App extends Component { config: Config = { pages: PAGES, }}


2.  适配层处理

1) 差异化功能处理

功能的差异化处理,使用配置层定义的全局变量来做,伪代码如下:

import TabBar from '../components/tabbar';export default class _C extends Component { render() { return {(WEAPPSOURCE == WBWEAPP) && <TabBar/>} }}

这样写的话,当WEAPPSOURCE !== WBWEAPP时,TabBar组件不会被打包到最终代码中,wxml文件中TabBar的代码块也不会有。上面的import是不需要做特殊处理,打包时会分析依赖关系,没有被最终使用的文件不会被编译。


2) 接口统一封装处理

在各个平台方小程序中,通用功能都应该是统一管理的。比如用户信息,用户在58同城小程序内进行登录,各业务都能拿到统一的用户信息,而不是进入新房页面后再做一次新房的登录。这些功能,由平台方提供接口,供业务方调用。但各个平台存在差异性,这些差异性就由适配层做统一的封装,对业务开发提供一致的接口。

比如获取城市信息:

export const getCityInfo = () => { if (WEAPP_SOURCE == WBWEAPP) { city_info = WBIndex.WB.getCityInfo() } else if (WEAPP_SOURCE == AJKWEAPP) { city_info = AJKIndex.Common.getCityInfo();  } }


原理解析

通过以上介绍,已经解决了我们对差异化开发的要求,同时适配层将平台接口差异牟平,业务开发也不需要关心所处环境。大家可能比较好奇,所有的小程序代码都放在一起管理,最终打包出来的代码大小是不是最优的?主要是以下两点:

 1)  在开发中注意利用条件编译来删除不必要的代码;
 2)  在打包时做依赖分析及打包优化,业务层尽可能做更少的事情;

依赖分析优化工作主要是由@tarojs/cli包来完成的,简化后的流程图如下:





首先是解析入口文件`app.tsx`,通过两次语法转换,一次语法遍历,得到了依赖的样式文件、依赖的js文件、app的配置等,以及入口文件app.js。样式文件编译成最终的app.css,依赖的js文件,通过拷贝或生成,放到指定的目录中,app配置生成app.json。

两次语法转换是不一样的,第一次是通用的语法转换,比如jsx语法的处理。第二次是差异化的转换,会根据当前转换的类型是入口文件、页面文件或组件文件做一些特殊处理。第二次转换时使用了babel-plugin-danger-remove-unused-import插件,会删除不必要的依赖引入。上文提到的TabBar组件,虽然是被引入了,但在不需要的场景下TabBar组件就不会被打包。这里需要注意引入的文件,不应该存在副作用。

解析完入口文件后,会得到app配置的pages列表,页面文件列表循环通过同样的过程,得到页面的样式、js、配置等,以及所依赖的组件列表。

组件文件的打包过程跟页面是基本一致的,区别点在于组件会依赖其他组件。

理解了整个打包的流程,上面的问题答案就比较清晰了,不在pages配置里的页面是不会最终打包输出的,没有被依赖到的文件也是不会经过打包处理的。


与平台小程序集成

小程序最终的集成发布有三种方式:独立发布、插件集成、分包集成。





多个小程序的不同集成方案

1. 插件集成发布

如果是通过小程序插件方式集成,平台小程序可以将接口统一挂载到插件的变量中,二者就桥接上了。

插件的index.js设置(上文WBIndex即为引入的此文件):

module.exports = {WB: {},}

平台小程序接口注入方法:

const plugin = requirePlugin("xinfang");plugin.WB = { getCityInfo: function() {}}


2. 分包集成发布

如果是分包集成的话,可以考虑将接口直接挂载在App中。

平台小程序接口注入方法(上文AJKIndex即为getApp()):

getApp().Common.getCityInfo = function() {}

采用分包集成方案的话需要注意,因为双方是在各自仓库下分别开发的,最终需要和到一起进行打包发布。目前我们采用的方案是配置`config.outputRoot`将结果代码打包到平台小程序仓库中,通过git管理,再由平台小程序做发布。


3.独立小程序发布

方案跟分包集成发布是一致的,不过API由自己提供,也挂载在App中,同时扮演了平台方和业务方。


实践经验分享

a) 小程序包依赖的json文件的处理,比如插件需要有插件配置文件`plugin/plugin.json`。可通过配置`config.copy.patterns`指定需要拷贝的文件或者目录来实现;
b) 小程序是插件和分包处理,在不同场景下的页面跳转路径是不一样的,但其实相对的路径是一致的,在于跳转前缀不同,可将页面跳转统一封装到适配层,根据环境变量适配不同的加上对应的前缀,当需要由插件切换到分包时,跳转部分仅需修改前缀,无需额外处理;

问题解决

前面提到一处开发多处运行的难题,得到了一一解决,整理如下:

a) 源码层面无法进行跨团队协作开发?

团队间分仓库开发,最终代码通过微信插件方式,或者分包方式进行集成。

b) 业务方与平台方之间的如何解耦?

通过统一的API,进行桥接,无其他耦合,API根据集成方式的不同,有不同的挂载方案。

c) 如何进行差异化开发?

针对样式差异化,配置差异化,功能差异化均给出了方法。

d) 如何保证打包结果是最优的?

尽可能的利用编译时的条件编译方法,排除不必要代码。

e) 平台方接口的差异性如何牟平?

增加了适配层,对业务提供一致的输入输出接口。

f) 支持不同平台小程序的多种接入方案?

支持了插件接入与分包接入。


总结与规划

本文介绍了在较复杂的小程序业务场景中,跨多小程序跨团队的协作方案,该方案帮助了新房业务在多小程序中的快速落地及迭代。

在实现了“58同城”小程序中的新房业务接入后,我们又做了“58同镇”的新房业务对接。只需要“58同镇”小程序提供一致的基础能力接口,即可轻松接入。

本文内容主要为业务经验积累,整体方案易于实施,带来的业务开发提效却是显著的,希望能帮助到大家。实际业务落地过程中,还有较多的细节需要处理,无法一一列举,欢迎提问或咨询。

文中仅介绍了业务在微信小程序的实践情况,实际上在百度小程序以及H5也已有相应落地实践,具备了一定的通用性,可以放心使用。

随着业务覆盖的范围越来越广,适配层会越来越复杂,不利于维护,更有效的方案是把业务实践总结为一套通用的接口标准,各个小程序按统一标准来实现API,业务方可以不关心所处环境的差异性,进一步提高跨团队开发的协作效率。 


参考文献

1. https://www.npmjs.com/package/cross-env

2. https://nervjs.github.io/taro/docs/config.html

3. https://webpack.js.org/plugins/define-plugin/

4. https://www.npmjs.com/package/uglifyjs-webpack-plugin

5. https://github.com/mishoo/UglifyJS2#compress-options 


作者简介

陈志庆 58同城架构师

叶春喜 58同城高级研发工程师



live

沙龙活动直播



2020年58技术沙龙活动在线直播第一弹——《大数据平台建设实践与探讨》已准备就绪,欢迎你强势围观!


详情请戳图片查看,2月22日本周六19:00,我们不见不散


END

阅读推荐




本文由快明科技整理发布,如需转载请联系852657156@qq.com

相关案例查看更多