有过小程序开发经验的都知道,在小程序的生态环境中,是很难做到像其他项目那样完全的CI的,因为我们的上传代码是只能在IDE中操作且代码是提交到微信服务器的,微信并没有提供接口让我们可以自动化部署代码。
一个我们项目中比较常见的问题是,我们本地开发好后,如果想上传代码到腾讯服务器上,需要将本地的一些配置项修改成线上的版本,比如我们的接口地址,项目配置信息等。当然你可以手动去维护,但是不提倡,因为项目如果逐渐增大,业务逻辑变得复杂的话,涉及到的修改项会逐渐增多,手动维护,很难保证不会出错,更有甚者会有人忘记修改直接提交然后苦苦找错,很浪费时间。
这里给大家提供的方案,是我自己根据微信小程序有限的开放能力整理出来的。
废话不多说,入题吧。
project.config.json
)如果你是使用IDE搭建的一个quick-start的小程序,那么你的目录结构不是像我上面那样的。你需要将你的项目调整为我上面的那样,其中可以通过npm init -y
来直接生成package.json
文件。修改好以后,别忘了修改你的项目根目录下的project.config.json
,添加下面的配置项以指定你的源码目录,否则会编译不会通过:
"miniprogramRoot": "src/",
在你的package.json
中添加npm scripts
,我这里只做演示,只添加了两个环境的切换脚本,如下:
"scripts": {
"switch:dev": "node switch.js --dev",
"switch:prod": "node switch.js --prod"
},
可以看到,我们实际运行的是,项目根目录下的switch.js
文件来实现的,接下来我们来实现这个命令脚本。
实现的思路:
接下来是代码实现,注释写的很详细:
/**
* 根据命令行运行参数,修改 /src/config.js 里面的项目配置信息
* 即动态的将 /config/env 下的配置文件的内容写入到 /src/config.js 中
*/
const fs = require('fs')
const path = require('path')
//源文件
const sourceFiles = {
prefix: '/config/env/',
dev: 'dev.json',
prod: 'prod.json'
}
//目标文件
const targetFiles = [{
prefix: '/src/',
filename: 'config.js'
}]
const preText = 'module.exports = '
// 获取命令行参数
const cliArgs = process.argv.splice(2)
const env = cliArgs[0]
// 判断是否是 prod 环境
const isProd = env.indexOf('prod') > -1 ? true : false
// 根据不同环境选择不同的源文件
const sourceFile = isProd ? sourceFiles.prod : sourceFiles.dev
// 处理数据
fs.readFile(__dirname + sourceFiles.prefix + sourceFile,
(err, data) => {
if (err) {
throw new Error(`Error occurs when reading file ${sourceFile}.\nError detail: ${err}`)
process.exit(1)
}
// 获取源文件中的内容
const targetConfig = JSON.parse(data)
const {
baseUrl
} = targetConfig
// 将获取的内容写入到目标文件中
targetFiles.forEach(function(item, index) {
let result = null
if (item.filename === 'config.js') {
let config = {
baseUrl: baseUrl
}
result = preText + JSON.stringify(config, null, 2)
}
// 写入文件(这里只做简单的强制替换整个文件的内容)
fs.writeFile(__dirname + item.prefix + item.filename, result, 'utf8', (err) => {
if (err) {
throw new Error(`error occurs when reading file ${sourceFile}. Error detail: ${err}`)
process.exit(1)
}
})
})
})
我们先用一个简单的配置来测试一下,假设我们本地开发和实际上线的项目中的请求的接口地址前缀是不一样的,我们需要为dev
和prod
环境各提供一个baseUrl
的配置项,修改配置文件:
/config/env/dev.json
文件:
{
"baseUrl": "dev server"
}
/config/env/prod.json
文件:
{
"baseUrl": "prod server"
}
此时假设我们/src/config.json
文件中的代码:
module.exports = {
"baseUrl": "dev server"
}
当我们项目需要上传到腾讯服务器的时候,此时在项目根目录下运行脚本:
npm run switch:prod
module.exports = {
"baseUrl": "prod server"
}
补充:我们可以在app.js
中引入config.js
文件,然后作为一个全局变量暴露出去,这样我们就可以在每个page中通过getApp().globalData.config
来获取这里的各项配置信息了。代码:
const config = require('./config')
App({
onLaunch: function () { },
globalData: {
userInfo: null,
config: config
}
})
由于每次上传代码时都要自己运行npm脚本来切换环境配置,可能也会有点不方便,所以我们可以使用小程序给我提供的一些钩子来实现自动运行脚本。
首先我们先打开配置项,输入我们要运行的脚本:
这会在我们的project.config.json
中生成如下的脚本,当然难你也可以手动的在这个文件中修改:
"scripts": {
"beforeCompile": "node switch --dev",
"beforePreview": "",
"beforeUpload": "node switch --prod"
}
这三个钩子的对应含义可以在小程序官方文档找到,可以自行参考。不过感觉很多开发者没有用到过。汗。
这是我自己在项目中配置,虽然本地编译的时候每次都会运行一下这个脚本,但是这一点的性能损失还是很微小的,不用care。
项目已经上传至github,地址:https://github.com/JerryYuanJ/Jmemo。欢迎issue,如果对你有帮助,欢迎star。