我们公司每个部门有各自独立开发的小程序,但最近Boss提出了新的需求,说想要把已经做好的小程序A中的某个独立子包移植到小程序B中;
但这件事情的难点在于:A 用的是原生小程序开发的;B 用的是Uniapp开发的;所以肯定是无法直接CV了;
想要解决这个需求我当时能想到的解决方案:
- 下策:
在小程序B中再重新完整做一遍功能。这种吃力不讨好的活必须PASS; - 中策:
使用转化代码的工具。但问题是这个项目会经常性修改需求,而且转化后的代码不尽如人意,经常有一些Bug,需要人工挨个筛选,是个大工程... - 上策:利用 Webpack,将已经开发完毕的原生分包直接移植到小程序B中;且以后无论在哪个小程序中改动该分包的内容,都可以一键拉取后实现快速迭代发布;
一起来看看具体如何实现吧
- 首先在Git上建立一个新的仓库,用于独立存放A原生小程序中分包里面的所有模块代码;如下是已经开发好的分包中包含的页面:
- 在小程序B的pages模块下新建一个文件夹(Weiguanjia2),并在该文件夹下拉取仓库中存放的公共代码;
- 修改vue.config.js中的内容(此处需要对CopyWebpackPlugin及编写插件有一定的了解)
js
const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')
class CopyOriginSubPackagePlugin {
constructor(subPackagesOptions = {}) {
// 微信原生的分包配置规则
this.subPackagesOptions = subPackagesOptions
}
apply(compiler) {
const that = this
compiler.hooks.emit.tap('CopyOriginSubPackage', (compilation) => {
// 找到app.json文件
const appJsonAssets = compilation.assets['app.json']
if (!appJsonAssets) {
return
}
try {
// app.json文件内容转成json格式
const source = JSON.parse(appJsonAssets.source())
// 添加一个默认的subPackages
const subPackages = (source.subPackages = source.subPackages || [])
// 把要集成的分包添加到app.json中
subPackages.push(that.subPackagesOptions)
// 将修改后的内容写入到文件中
const fileContent = JSON.stringify(source, null, 2)
compilation.assets['app.json'] = {
source() {
return fileContent
},
size() {
return fileContent.length
}
}
} catch (e) {
console.log('[CopyOriginSubPackagePlugins Error]', e)
}
})
}
}
const plugins = []
if (process.env.UNI_PLATFORM === 'mp-weixin') {
plugins.push(
new CopyWebpackPlugin([
{
from: '分包的当前路径',
to: '编译后的输出路径'
}
]),
// 配置分包页面路由
new CopyOriginSubPackagePlugin({
root: 'pages/WeiGuanJia',
pages: [
// ...将分包中的所有页面都添加进来
]
})
)
}
module.exports = {
configureWebpack: {
plugins
}
}
- 编译uniapp,在微信开发者工具中打开编译后的小程序即可大功告成;
如何区分小程序A、B中不同的接口、变量、功能权限呢?
从总体来看,A、B小程序中针对该模块的功能90%以上都是可以共用的,因此完成上述配置,基本代表分包移植成功; 但由于业务的要求有差异,所以两者在接口域名、权限、某些页面的展示上需要做一定的区分;
那么我们如何使用同一套代码进行区分呢?
- 首先分别在两个小程序中新建配置文件;(此文件我放在了utils/disposition.config.js);
- 配置文件中的内容要根据项目实际情况而定,比如可以导出一些特殊的产品字段,授权接口等;
js
export let product = 'xxx'
export let shopInfo = xxx
.....
// 授权接口
export const Auth = async () => {
xxxx调用授权接口的逻辑
}
- 在App.vue中导入该配置文件,并把文件中导出的所有内容都加到globalData中;
js
import * as allDispositionConfig from './utils/disposition.config'
export default{
onLaunch:()=>{},
onShow:()=>{},
onHide:()=>{},
globalData:{
...
allDispositionConfig
}
}
4.在其他文件中,可以用 getApp().globalData.allDispositionConfig.xxx 的方式访问配置文件中独有的变量/方法;
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这是我能想到的开销比较小的解决方案,对于类似的情况如果大家有什么其他好的建议,欢迎一起讨论!