微信小程序由于生态圈的封闭性,很多功能不支持或者实现起来很繁琐,这次就分享一下项目里对于小程序服务器切换相关的配置及使用心得。
首先要解释一下后面会出现的两个变量名:
- SERVER_MODE: 综合性的切换服务器模式,通过在代码里手动修改配置文件里的服务器模式值,用于测试、预发及上线时的版本切换及环境模式判断,包括各个接口服务器、h5域名服务器、第三方appId、自定义服务器等一键切换。
- SERVER_DEV_MODE:接口api的切换服务器,通过在特定入口里打开特定页面,在该页面里可选切换api服务器环境,用于开发及测试人员根据需要自行切换api服务器来进行测试。
- (敲黑板:前者是修改代码,综合切换各个配置;后者是在页面里实时选择,仅切换api接口请求服务器)
将从以下几个地方点做配置说明:
一、项目配置文件config
因为小程序前端本身无法判断所处的版本是开发版、体验版还是线上版,那通过这个SERVER_MODE一键切换配置就相当于自行定义了运行版本的判断,能够方便实现开发测试阶段的差异化配置,提升效率。
我这里是config文件夹里分了三个js文件:
- 一个是服务器域名、基础路径以及第三方插件appId等综合相关的配置 keyData.js:
// api服务器
const data_API_BASE = {
prod: 'https://app.abc.com/api/api',
beta: 'https://beta.test.abc.com/api/api',
test: 'https://test.abc.com/api/api',
}
// 商城h5页面host
const data_H5_HOST = {
prod: 'https://app.abc.com',
beta: 'https://beta.test.abc.com',
test: 'https://test.abc.com',
}
// 友盟AppKey
const data_UM_KEY = {
prod: 'abc',
beta: 'bcd',
test: 'def'
}
export default {
init (SERVER_MODE) {
let key
switch (SERVER_MODE) {
case 1: // 线上
key = 'prod'
break
case 2: // 预发
key = 'beta'
break
case 3: // 测试
key = 'test'
break
case 9: // 自定义
key = 'test'
break
default:
console.warn('环境模式值有误')
}
return {
API_BASE: data_API_BASE[key],
H5_HOST: data_H5_HOST[key],
UM_KEY: data_UM_KEY[key]
}
},
}
- 第二个是h5页面地址相关的配置 webData.js:
/**
* h5页面地址
*/
export default {
init (H5_HOST) {
// 签到页
const H5_SIGN = `${H5_HOST}/h5/sign/#/index`
// 平台攻略
const H5_STRATEGY = `${H5_HOST}/h5/common/#/strategy`
return {
H5_SIGN,
H5_STRATEGY,
}
}
}
- 第三个就是引入了以上两个js文件的入口配置文件 index.js:
/**
* 全局配置文件
*/
import keyData from './keyData.js'
import webData from './webData.js'
// 一键切换环境模式 (1:线上, 2:预发, 3:测试, 9:自定义)
const SERVER_MODE = 3
// app版本号
const VERSION_APP = '2.2.1'
const getConfig = () => {
/**
* 获取一键切换后的值
*/
let SERVER_DEV_MODE
if (SERVER_MODE === 1) {
SERVER_DEV_MODE = SERVER_MODE
} else {
SERVER_DEV_MODE = +wx.getStorageSync('SERVER_DEV_MODE') || SERVER_MODE
}
const keyConfig = keyData.init(SERVER_DEV_MODE)
/**
* 自定义测试模式配置
*/
if (SERVER_MODE === 9) {
// **************************************************************************
keyConfig.API_BASE = 'https://shoptest.abc.com/api/api'
keyConfig.H5_HOST = 'https://shoptest.abc.com'
}
/**
* 获取h5页面地址
*/
const h5Config = webData.init(keyConfig.H5_HOST)
return {
...keyConfig,
...h5Config,
SERVER_DEV_MODE
}
}
module.exports = {
getConfig,
VERSION_APP,
SERVER_MODE,
}
- 如上代码所示,该配置的都配置好,每次在上线时就把SERVER_MODE的值改为1,然后上传代码提交审核即可,非常方便。
- 只要遵守上述上线步骤,那么可以认为,当SERVER_MODE为1时,小程序是运行在线上版里,当SERVER_MODE不是1时,小程序是运行在体验版或开发版里,这样就可以通过判断SERVER_MODE值来对线上版和非线上版做一些差异化处理了,比如非线上版强制用户打开开发者调试,方便记录日志定位bug等。
- 如上index.js导出了一个函数getConfig,之所以导出为一个函数,而不是直接导出服务器环境的配置结果,是为了在页面里切换api服务器也能即时生效。在页面里切换api服务器时会改变SERVER_DEV_MODE的值,存储在Storage里,每次接口请求时都在统一封装的请求方法里调用这个getConfig函数获取实时的api服务器配置值来发送接口请求,这样就实现了api服务器切换的效果。
二、小程序入口文件app.js
为了方便且高效的获取项目的配置信息,我把配置信息都存储在了小程序的全局公共变量globalData里:
const config = require('./config/index') // 全局配置文件
App({
// 全局公共变量
globalData: {
config: { // 全局配置
...config.getConfig(),
VERSION_APP: config.VERSION_APP,
SERVER_MODE: config.SERVER_MODE,
}
}
})
- 注意这里是把getConfig函数调用后的结果存在了globalData里,小程序入口文件也仅在刚启动小程序时调用一次,所以这里存储的是刚启动小程序时的配置信息。
三、接口请求统一封装http.js
const config = require('../config/index')
// 伪代码,只需要关注url值的获取
wx.request({
url: config.getConfig().API_BASE,
data: data,
method: 'POST',
timeout: 10000,
header: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
},
......
})
- 这里接口请求的地址url取的getConfig().API_BASE,由于每次接口请求都是实时调用的getConfig函数,所以得到的api服务器接口地址也是实时最新的。
四、切换服务器的页面实现
serverMode.wxml:
<!-- 服务器环境切换 -->
<view class="server" wx:if="{{SERVER_MODE !== 1}}">
<view class="itemList">
<radio-group bindchange="radioChange">
<label class="itemWrap" wx:for="{{itemsList}}" wx:key="value">
<view class="value">
<radio value="{{item.value}}" checked="{{checkedValue === item.value}}"/>
</view>
<view class="name">{{item.name}}</view>
</label>
</radio-group>
</view>
</view>
serverMode.js:
const app = getApp()
const gData = app.globalData
const config = require('../../../../config/index') // 全局配置文件
Component({
data: {
SERVER_MODE: gData.SERVER_MODE,
itemsList: [
{ value: 1, name: '线上环境' },
{ value: 2, name: 'beta环境' },
{ value: 3, name: 'test环境' },
],
checkedValue: 0
},
methods: {
onShow () {
this.setData({
checkedValue: gData.config.SERVER_DEV_MODE
})
},
radioChange (e) {
const val = e.detail.value
wx.setStorageSync('SERVER_DEV_MODE', val + '') // 持久化存储在小程序storage里
gData.config = config.getConfig()
wx.reLaunch({
url: '/pages/index/index'
})
}
}
})
serverMode.wxss:
.server{padding:40rpx;color:#666}.server .itemWrap{display:flex;margin-bottom:60rpx}.server .itemWrap .name{margin-left:10rpx}
serverMode.json:
{
"navigationBarTitleText": "切换服务器环境",
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black",
"backgroundTextStyle": "dark"
}
- 由于小程序不支持关闭及重启操作,所以就设置的切换服务器后relaunch到小程序首页,防止缓存导致的数据错乱。
- 页面入口放哪就取决于你的项目需要了,我这里是在个人设置页面加了个入口,但是要注意判断下SERVER_MODE的值,值为1表示是线上环境,就隐藏这个入口,万事大吉。