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

导语

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

背景

目前市面上小程序端越来越多,跨平台开发框架逐渐成为开发小程序的主流。目前跨平台开发有较多的开源解决方案,比如美团点评的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"',0);">AJKWEAPP'"ajkweapp"',254);'>2) 差异性样式处理

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

const sassConfig = {

wbweapp: '../wbweapp.scss',0);">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'],0);">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 _C Component {

render() {

return {(WEAPPSOURCE == WBWEAPP) && <TabBar/>}

}

}

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

2) 接口统一封装处理

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

比如获取城市信息:

原理解析

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

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: {},254);'>平台小程序接口注入方法:

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同城高级研发工程师

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


概述 消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。 订阅消息推送位置:服务通知 订阅消息下发条件:用户自主订阅 订阅消息卡片跳转能力:点击查看详情可提爱转至该小程序的页面 消息类型 一次性订阅消息 一次性订阅消息用于解决用户使用小程序后,后续服务
判断H5页面环境在微信中还是小程序中 用小程序提供的wx.miniProgram.getEnv可以获取环境参数 &lt;script type=&quot;text/javascript&quot; src=&quot;https://res.wx.qq.com/open/js/jweixin-1.
wx.reLaunch和wx.navigateTo,wx.navigateTo的区别 2019-03-23 11:18:05 wx.navigateTo 用于保留当前页面、跳转到应用内的某个页面,使用 wx.navigateBack可以返回到原页面。对于页面不是特别多的小程序,通常推荐使用 wx.n
微信小程序如何从数组里取值_微信小程序 传值取值的几种方法总结 小程序里常见的取值有以下几种,一个完整的项目写下来,用到的概率几乎是100%。 列表index下标取值 页面传值 form表单取值 1. 列表index下标取值 实现方式是:data-index=&quot;{{index}}&quot
H5项目接入微信授权登录,通过 UA 区分微信还是普通浏览器: let&#160;ua&#160;=&#160;navigator.userAgent.toLowerCase(); let&#160;isWeixin&#160;=&#160;ua.indexOf(&#39;micromessenge
微信小程序获取data-xx=&quot;&quot;属性的值,自定义属性设置和获取(data-) 微信小程序&lt;view class=&quot;details-btn&quot; data-taskId=&quot;111&quot; bindtap=&#39;taskdetails&#39
小程序报错:TypeError: Cannot read property ‘addEventListener‘ of undefined 解决办法 将调试基础库由2.16.0(或者当前的) -&gt; 2.14.1 解决问题
H5跳转微信小程序-成功案例(VUE)(踩坑无数) TuoMei 已于 2022-07-29 09:52:22 修改 准备工作 根据官方提供的资料需准备以下几点: 1、已认证的服务号 2、绑定JS接口安全域名 (在微信公众平台设置) 3、IP白名单 (在微信公众平台设置) 4、将小程序和H5公众号进
微信小程序 页面跳转和数据传递实例详解 这篇文章主要介绍了微信小程序 页面跳转和数据传递实例详解的相关资料,这里附有实例代码帮助到家学习理解,需要的朋友可以参考下 微信小程序 页面跳转和数据传递 1.先导 在Android中,我们Activity和Fragment都有栈的概念在里面,微信小程序页面也
情景1.拉取公司代码演示: 因为github有墙,这里我们以gitee(码云)为例作为演示 (其实就是国产github,也非常好用~) 步骤一:打开Git界面 先在一个空文件夹右击Git Bash Here,打开git界面 步骤二:输入克隆远程仓库指令 别人复制的链接在这里获取 拿到别人赋值的链接自
如何开发微信小程序? 作为一名10多年一直从事互联网平台开发的从业者,我来回答下这个问题吧。 微信小程序开发流程总体可以归纳为4个步骤, 老张带您捋一捋整个环节,小白用户可以收藏了。 好了废话不多说,开始! 一、开发前小程序需要准备的资料 我们在开发微信小程序前,需要准备下相关资料。这个资料主要是后
原生小程序开发优化方案 为了更好的制定优化方案,我们 有必要先了解下小程序的底层架构、以及与普通网页开发的差异 小程序最终渲染载体与当下一些热门的技术 Flutter、React Native等不同,依然是浏览器内核,而不是原生客户端。 而对于传统的网页来说,UI 渲染和 JS 脚本是在同一个线程中
1,不要下两倍尺寸的图片, 小程序本身自己就会对元素缩小两倍,设计图片的一杯就已经很清晰了。 2,图片压缩,(主要是压缩静态资源,ps 可以压缩,然后有一些在线压缩工具,保持600-800kb 的静态) 3,通用的代码组件化 4,是在工程量太大可以分包,分包现在最大支持20m(一般都不会去分包的)
文章浏览阅读189次。人工智能研究实验室OpenAI在2022年11月30日发布了自然语言生成模型ChatGPT,上线两个月就已经超过一亿用户,成为了人工智能界当之无愧的超级大网红。ChatGPT凭借着自身强大的拟人化及时应答能力迅速破圈,引起了各行各业的热烈讨论。简单来说ChatGPT就是可以基于用户文本输入自动生成回答的人工智能聊天机器人。那肯定会有人说这不就是Siri嘛,虽然都是交互机器人但是两者的差别可老大了。那么ChatGPT在人机交互时为什么会有这么出色的表现?它到底会不会取代搜索引擎?90%的人真的会因为ChatG
文章浏览阅读193次。8. 导航和路由管理:掌握小程序的导航方式,如使用wx.navigateTo跳转页面、使用wx.redirect重定向页面等,学会实现页面之间的跳转和传参。1. 小程序的基本概念和架构:了解小程序的定义、特点以及与传统APP的区别,掌握小程序的运行环境、组件和API等基本概念。10. 支付功能:学习小程序的支付方式,如微信支付、支付宝支付等,了解支付流程和注意事项,学会实现小程序的支付功能。9. 用户授权和登录:了解小程序的用户授权机制,如获取用户信息、调用微信API等,学会实现用户的登录和注册功能。_微信小程序开发知识点总结
文章浏览阅读4.8k次,点赞7次,收藏18次。一、准备工作1. 安装微信开发者工具,并登录微信小程序账号;2. 准备斗地主游戏的图片资源;3. 准备斗地主游戏的音效资源;二、创建小程序1. 打开微信开发者工具,点击“新建小程序”,输入小程序名称,选择小程序的项目目录,点击“创建”;2. 在小程序的项目目录中,新建文件夹“images”,将准备好的斗地主游戏的图片资源放入“images”文件夹中;3. 在小程序的项目目录中,新建文件夹“sounds”,将准备好的斗地主游戏的音效资源放入“sounds”文件夹中;三、编写代码1. 在小程_扑克牌微信小程序代码
文章浏览阅读3.9k次,点赞3次,收藏7次。一、准备工作:1. 安装微信开发者工具,创建小程序项目;2. 准备游戏角色图片;3. 准备游戏背景音乐;二、实现步骤:1. 创建游戏页面,添加游戏角色图片,添加游戏背景音乐;2. 创建游戏角色类,定义游戏角色属性,如角色名称、角色图片、角色能力等;3. 创建游戏类,定义游戏属性,如游戏人数、游戏角色、游戏规则等;4. 创建游戏控制类,定义游戏流程,如游戏开始、游戏结束、游戏角色分配等;5. 创建游戏界面,实现游戏流程,如游戏开始、游戏结束、游戏角色分配等;6. 创建游戏结果页面,显示游戏_微信小程序游戏代码
文章浏览阅读1.7k次。1. 创建小程序项目:使用微信开发者工具创建一个小程序项目,并在项目中添加一个页面,用于模拟聊天。 2. 定义数据结构:定义一个数据结构,用于存储聊天记录,包括发送者、接收者、消息内容等信息。 3. 实现聊天功能:实现聊天功能,包括发送消息、接收消息、显示消息等功能。 4. 实现界面:使用微信小程序的界面框架,实现聊天界面,包括聊天记录列表、输入框等。代码示例:// 定义数据结构var chatData = { sender: '', receiver: '', message: '' };_制作聊天对话小程序代码
文章浏览阅读2.1k次。1、创建小程序项目:使用微信开发者工具,新建一个小程序项目,输入项目名称,选择项目目录,点击“创建”按钮,即可创建小程序项目。2、添加页面:在小程序项目中,可以添加多个页面,每个页面都有自己的页面文件,比如首页、分类页、购物车页、我的页面等。3、添加组件:在小程序项目中,可以添加多个组件,比如商品列表组件、购物车组件、订单组件等,用于在页面中显示商品信息、购物车信息、订单信息等。4、添加接口:在小程序项目中,可以添加多个接口,用于获取商品信息、购物车信息、订单信息等,以便在页面中显示。5、_微信开发者工具做一个我的商城