E企盈营销工具技术服务商 热线:4006-838-530

微信应用分身,一套代码生成多个小程序

E企盈直播平台营销卖货系统

前言影分身术,看过火影的都知道,一个本体,多个分身。大家肯定要问了,那小程序开发跟影分身术也能扯上关系?没错,那自然就是:一套代码,多个小程序啦。各位先别翻白眼,且听我细细说来。如今小程序发展如日中天,再加上微信的力推,很多公司的业务也都慢慢的转向小程序,这让我这个安卓开发,也不得不开始了小程序开发之旅。然而随着公司的发展,客户越来越多,核心功能相同的小程序,需要上架多个小程序分别给不同的客户使用,每个小程序之间又存在这一小部分的定制化,比如界面展示的不同、小功能的差异等等。这可让我这个刚接触小程序开发的前端菜鸟抓狂了,每个小程序复制一份代码出来,然后做定制化的修改?这岂不是如果哪天核心业务有改动,我得对每套代码分别改动一次?不行,即使是菜鸟,对这种弄出多套重复代码的行为也是无法容忍的!于是,就有了针对这种场景下的一个解决方案:给小程序开发来个影分身术。Github地址:该项目基于Taro框架,由凹凸实验室开源,非常感谢他们的努力付出。之所以选用Taro,主要是因为它采用React语法标准,而本人之前有过ReactNative开发经验。由于本人接触前端开发时间不长,文中若出现了错误或者有更好的方案,欢迎各位包容和指正,万分感谢。影分身之基础配置影分身的能力,主要来源于Taro所提供的编译能力,所以需要对Taro的和编译配置有所了解。我们先来看看配置的相关文件目录:config目录为Taro初始化后的默认配置目录,图中蓝色框框内的三个文件(dev、index、prod)为默认生成的配置文件,剩下的文件,则为分身所需的配置。图中配置了三个分身,我们以channel1为例,config是该分身的一些配置,project.config.json就是该分身小程序的基本配置,如:{u0026quot;miniprogramRootu0026quot;:u0026quot;./u0026quot;,u0026quot;projectnameu0026quot;:u0026quot;channel1u0026quot;,u0026quot;descriptionu0026quot;:u0026quot;channel1u0026quot;,u0026quot;appidu0026quot;:u0026quot;wx8888888888888u0026quot;,…}channel.js文件,则是用来指定,当前需要编译哪个小程序,如:module.exports={channel:’channel1′}在默认的编译配置入口文件index.js中,我们需要配置小程序的输出目录,配置如下:constchannelInfo=require(‘./channel’)constconfig={…//输入目录为dist_channel1outputRoot:’dist_’+channelInfo.channel,…//讲config/channel1/project.config.json文件拷贝到dist_channel1下copy:{patterns:[{from:’config/’+channelInfo.channel+’/project.config.json’,to:’dist_’+channelInfo.channel+’/project.config.json’}],…}…}执行Taro的后,将会生成该分身对应的小程序代码文件夹dist_channel1,直接使用小程序开发者工具打开该目录,就可以进行channel1小程序的预览了。通过这些配置,我们就可以通过同一套代码,生成多个不同的小程序啦!当然,这些小程序的内容是完全一样的,顶多就是project.config.json中配置的名字、appid有不同而已。那么下面,我们就开始看看如何实现生成多个有差异化的小程序。在具体实现之前,我们需要知道Taro两个重要的配置:;。影分身之样式分身首先,我们来看看最常见的一种需求,那就是不同小程序之间,样式上的差别。我们先来看两张图。小程序A:小程序B:在样式上,这两个小程序目前的区别有:主色调不同对应图片资源不同排列样式不同建立分身目录第一步,在src下为每个分身小程序建立一个目录,名字最好与channel.js中的配置一样,如下图:放置样式差异以之前的“小程序A”来举例:其中assets文件夹就是该小程序的资源文件,即各种蓝色的图标。app.less为全局的样式文件,内容如下:@main_color:#1296db;.main_color_txt{color:@main_color}ChannelStyle.ts文件则为可能在代码中需要用到的样式:constChannelStyle={mainColor:’#1296db’}exportdefaultChannelStyle配置别名在放置好各类样式差异后,就可以进行全局变量和别名的配置了,在项目的config下的index.js中做如下配置:constconfig={…alias:{‘@/channel’:path.resolve(__dirname,’..’,’src/channel/’+channelInfo.channel),’@/assets’:path.resolve(__dirname,’..’,’src/channel/’+channelInfo.channel+’/assets’),’@/app_style’:path.resolve(__dirname,’..’,’src/channel/’+channelInfo.channel+’/app.less’),}…}这样,在代码中就可以通过别名进行引用了://代码中需要用到ChannelStyle中的样式importChannelStylefrom’@/channel/ChannelStyle’//app.tsx入口文件引用全局样式import’@/app_style’//引用资源图片u0026lt;Imagesrc={require(‘@/assets/icon.png’)}/u0026gt;另外请注意,由于目前Taro还未在.less等样式文件中支持别名,所以无法通过类似@import‘@/app_style’的方式进行引用,所以目前需要在每个分身包下放置全量的差异样式。配置全局变量由于对于TabBar的配置,是纯字符串的形式,无法通过别名配置,所以需要使用另一种配置方式,也就是全局变量,在index.js的配置方式如下:constconfig={defineConstants:{ASSETS_PATH:’channel/’+channelInfo.channel+’/assets’}}但是主色调每个分身都不一样,所以需要在分身的配置文件中配置,就是基础配置中,分身文件夹下的config.js,在其中加入全局变量的配置:module.exports={…defineConstants:{MAIN_COLOR:’#1296db’},…}全局变量在代码中可以直接使用,如app.tsx中TabBar的配置:config:Config={…tabBar:{…selectedColor:MAIN_COLOR,list:[{pagePath:’pages/index/index’,text:’首页’,iconPath:ASSETS_PATH+’/home_u.png’,selectedIconPath:ASSETS_PATH+’/home_s.png’},…]}}配置合并在配置完成之后,在index.js文件最后的合并代码中,加上我们定义的分身配置:module.exports=function(merge){…//默认的原始代码为returnmerge({},config,envConfig)returnmerge({},config,envConfig,require(‘./’+channelInfo.channel+u0026quot;/configu0026quot;))}样式分身小结如此,根据“小程序B”的资源文件和主题色配置之后,通过修改channel.js中的编译分身名,就可以生成这两个小程序了。我们可能还发现,“小程序A”和“小程序B”的样式差异,除了资源图片和主题色之外,“开发”页面的布局方式也有差异,这该怎么处理呢?没错,还是通过别名指定less文件的方式,为各页面指定对应的样式文件。如果说在实际业务中,不同的小程序存在明显的主题样式风格差异的话,建议可以建立主题包,然后为不同的小程序分身配置不同的主题包,如://分身配置module.exports={…alias:{‘@/theme’:path.resolve(__dirname,’..’,’../src/theme/theme1′),…}…}//文件引用import’@/theme/dev.less’影分身之功能分身除了样式差异之外,有定制化属性的小程序一定也会存在一定的功能性差异。细心的小伙伴可能发现了,“小程序A”和“小程序B”开发页面的条目数是不一样的。“小程序A”并没有FireWall这一项,而且,这两个小程序的前两个条目Java和JSX的顺序是不一样的。不仅如此,如果运行小程序,点击各项的话你会发现,点击C++这一项,“小程序B”是跳转到条目详情页面,而“小程序A”则是跳转到“管理”Tab页。类似这种功能性的差异,我们该如何处理呢?定义页面配置我所想到的思路是,给具有差异化的页面,提供差异化的配置项,然后通过合并的方式,合并具有差异的分身配置。我们先来看定义完成后的配置目录,该目录在src下:以“开发“页面为例,在DevConfig.ts中,我定义了如下的配置:importTarofromu0026quot;@tarojs/tarou0026quot;;//页面配置exportdefault{dev:{items:{//条目item1:{//条目1img:require(‘@/assets/jsx.png’),//图片txt:’JSX’,//文字onItemClick:()=u0026gt;{//点击跳转事件toPage(‘JSX’,require(‘@/assets/jsx.png’))}},item2:{…},…}}}//页面跳转functiontoPage(title,img){Taro.navigateTo({url:’/pages/dev/DevInfo?title=’+title+’u0026amp;img=’+img})}定义差异合并同时,diff包下的ChannelConfigDiff.ts文件,作为差异配置文件,其内容如下:exportdefault(config,merge)=u0026gt;{returnmerge([{},config])}可以看出,这其实就是把传入的config原封不动的返回了,因为对于项目主体来说,config是不需要改变的,具体的用途,会在下面说明。而MultiChannelConfig.ts则为最终的各页面配置,内容如下:importmergefrom’deepmerge’importChannelConfigDifffrom’@/diff/ChannelConfigDiff’//开发页面配置importDevConfigfrom’./pages/DevConfig’//合并基本页面配置constbaseConfig=Object.assign({},DevConfig)//合并差异页面配置constconfig=ChannelConfigDiff(baseConfig,merge.all)//开发页面最终配置exportconstdevConfig=config.dev定义差异配置在上面的定义中,我们发现ChannelConfigDiff是根据别名引用的,现在大家应该明白ChannelConfigDiff.ts文件的作用了吧?没错,就是通过在各分身中加入这个文件,并编写配置。以“小程序A”为例,diff目录如下:在channel2的ChannelConfigDiff.ts中,只需要配置具体的差异项即可,未配置的则采用默认的配置:constdev={dev:{items:{item1:{//定义第一个item为java内容img:require(‘@/assets/java.png’),txt:’Java’,onItemClick:()=u0026gt;{toPage(‘Java’,require(‘@/assets/java.png’))}},item2:{…},//第二个item为jsx内容item5:null,//第五个item(FireWall)为空item8:{onItemClick:()=u0026gt;{//最后一个item(C++)点击后跳转TABTaro.switchTab({url:’/pages/index/Manage’})}}}}}//将dev配置合并到原始整体配置exportdefault(config,merge)=u0026gt;{returnmerge([{},config,dev])}可以看到,该配置中,将item1(原jsx)和item2(原java)的内容对调,将item5(原FireWall)置空,将item8(原C++)点击事件改变。通过这些配置,以达到实现“小程序A”中的功能差异。最后,别忘了别名的定义,在index.js中,别名配置为:’@/diff’:path.resolve(__dirname,’..’,’src/config/diff’),在channel2的config.js中,别名配置为:’@/diff’:path.resolve(__dirname,’..’,’../src/channel/channel2/diff’),功能分身小结如果有了其他的页面差异的话,通过类似的增加配置,来进行差异化处理,文件的目录格式并无要求,只需要保证配置文件名一致、别名配置正确就可以了。这时,编译过后,生成的“小程序A”就拥有样式和功能差异化的“开发”页面了。通过这种方式进行差异化配置,就要求对业务有较好的理解和对组件的合理拆分,并且定义出合理的配置项。影分身之大差异分身即便使用了样式分身和功能分身,依然可能出现一些巨大差异的定制化需求,这些巨大的差异导致样式分身和功能分身的配置成本过大,那这种情况下,该如何是好呢?如果真的出现这种情况,那也只好断臂求生了——那就是整体页面的替换。我们来看看“小程序A”和“小程序B”的“管理页面”:小程序A:小程序B:编写新页面我们假设“小程序B”的“管理”页很难通过配置的方式去做差异化,那么这时,我们只有专门写一个新页面,目录如下:其中pages下的就是专属于channel3的页面。页面替换替换页面的方式,其实也是通过全局变量。index.js:defineConstants:{PAGE_MANAGE:’pages/index/Manage’,}channel3的config.js:defineConstants:{PAGE_MANAGE:’channel/channel3/pages/index/Manage’},app.tsx的页面配置:config:Config={pages:[…PAGE_MANAGE],…tabBar:{…list:[…{pagePath:PAGE_MANAGE,…}]}}如此,编译后,channel3生成“小程序B”的“管理”页面,就是channel3独有的页面了。总结本文所提供的,只是我能够想到的一种解决“多个核心功能类似的小程序需要维护多套代码”这种窘境的方法,如果有更好的方法,希望各位能够告诉我,非常感谢。由于本人只是一个刚接触前端不久的安卓开发,还有许多需要学习的地方,如果文中有误,欢迎指正批评。具体的代码可以到Github查阅,也欢迎各位Star和提Issue。最后,再次贴一下Github地址:更多内容,请关注前端之巅。会议推荐2019年6月,GMTC全球大前端技术大会2019即将到来。小程序、Flutter、移动AI、工程化、性能优化…大前端的下一站在哪里?点击下图了解更多详情。

赞(0) 打赏
未经允许不得转载:E企盈小程序开发-热线:4006-838-530 » 微信应用分身,一套代码生成多个小程序
分享到: 更多 (0)
E企盈小程序直播营销卖货系统
E企盈直播平台营销卖货系统

评论 抢沙发

E企盈小程序开发

联系我们联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏