# 小程序批量化代码提交 | 版本号 | 功能 | 描述 | |-------|-----------|-----------| | 1.0.0 | 批量化同步提交代码 | 批量化代码提交功能 | ## 快速开始: ``` // 单个小程序执行 npm run upload -- --t=2 --a=蓝晶甄享空间 --v=1.7.3 --d=优化一些问题 // 批量化执行 npm run upload -- --t=1 --v=1.7.3 --d=优化一些问题 ``` 1. 复制批量化功能代码文件到项目目录destroy(没有则创建) 2. destroy/upload.wx.js 单个小程序上传 ``` const ci = require('miniprogram-ci'); const fs = require('fs'); const path = require('path'); // 接收主进程传递过来的参数 process.on('message', async (data) => { let {appid, name, version, desc, env, appindex} = data await setProjectConfig(appid); await setConfig(appid); const project = new ci.Project({ appid: appid, type: 'miniProgram', projectPath: path.resolve(__dirname, '../'), privateKeyPath: path.resolve(__dirname, `../destroy/keys/private.${appid}.key`), ignores: ['node_modules/**/*', 'destroy/**/*'], }); // 上传 const uploadResult = await ci.upload({ project, version: version, desc: desc, setting: { es6: true, minifyJS: true, minifyWXML: true, minifyWXSS: true, minify: true }, onProgressUpdate: (e) => { // console.log('onProcessUpdate', e) if (e._status == "done" && e._msg == "upload") { console.log(`${appid}--${name}--${env} 上传完成`); // config.appindex += 1; } }, }); process.send('success'); process.exit(); }); // 设置 project.config.json const setProjectConfig = async (appid) => { // 读取和替换的文件路径 const project_config = '../project.config.json'; const promise = new Promise((resolve, reject) => { // 读取 project.config.json fs.readFile( path.join(__dirname, project_config), 'utf8', (err, data) => { if (err) throw err; let json = JSON.parse(data); // 替换appid json.appid = appid; // console.log('project.config.json:', json) // 改写 project.config.json 中 appid fs.writeFile( path.join(__dirname, project_config), JSON.stringify(json, null, 4), (err) => { if (err) throw err; resolve(); } ); } ); }); return promise; } // 设置config.js const setConfig = async (appid) => { // 读取和替换的文件路径 const config_file = '../config/config.js'; const promise = new Promise((resolve, reject) => { // 读取 config.js fs.readFile( path.join(__dirname, config_file), 'utf8', (err, data) => { if (err) throw err; let configjs = data; const current_appid = appid; // 替换文件中当前小程序的appid const regex = new RegExp('(current_appid\\s*=\\s*["\']).*?(["\'])', 'g'); configjs = configjs.replace(regex, 'current_appid = \'' + current_appid + '\''); // console.log(configjs) // 改写 config.js 中 current_appid fs.writeFile( path.join(__dirname, config_file), configjs, (err) => { if (err) throw err; resolve(); } ); } ); }); return promise; } ``` 3. destroy/upload.main.js 批量处理逻辑 ``` const {fork} = require('child_process'); const fs = require('fs'); const path = require('path'); let config = { appIds: [], // 小程序appid version: "",//版本号 desc: "",//版本描述 env: '正式环境' } function publishMiniProgram(options) { return new Promise((resolve, reject) => { const child = fork('./destroy/upload.wx.js'); // console.log('入参:',options); child.send(options); child.on('message', (msg) => { if (msg.error) { reject(new Error(msg.error)); } else { resolve(msg); } }); child.on('error', reject); child.on('exit', (code) => { if (code !== 0) { reject(new Error(`child process exited with code ${code}`)); } }); }) } exports.start = async () => { try { const file = await fs.promises.readFile( path.join(__dirname, '../destroy/config.json'), 'utf-8' ); const fileJson = JSON.parse(file); config = { ...config, appIds: fileJson.appIds, version: fileJson.version, desc: fileJson.desc, env: fileJson.env || '正式环境', }; console.log(`本次提交小程序: ${config.appIds.map(item => `${item.name} (${item.appid})`).join(', ')}`); console.log(`版本: ${config.version}`); console.log(`环境: ${config.env}`); console.log(`描述: ${config.desc}`); // 3. 顺序发布(避免并发资源竞争) let successCount = 0; let failedCount = 0; for (const [index, item] of config.appIds.entries()) { try { console.log(`\n开始发布第 ${index + 1} 个小程序: ${item.name} (${item.appid})`); await publishMiniProgram({ appid: item.appid, name: item.name, version: config.version, desc: `${config.env}——${config.desc}`, env: config.env }); successCount++; console.log(`✅ 发布成功: ${item.name}`); } catch (err) { failedCount++; console.error(`❌ 发布失败: ${item.name}`, err.message); } } // 4. 返回统计结果 return { success: successCount, failed: failedCount, }; } catch (e) { console.error('❌ 启动发布流程失败:', e.message); throw e; } } ``` 4. destroy/config.json 配置文件(版本号,版本描述,需要处理的小程序) ``` { "version": "2.4.2", "desc": "2.4.2 优化一些问题", "env": "正式环境", "appIds":[ { "name":"xxxxxx", "appid":"xxxxxx" } ] } ``` 5. destroy/keys/* 小程序密钥文件(小程序后台“开发与服务”-“开发管理”) ![img.png](img.png) 需要下载小程序代码上传密钥,放到keys文件夹中,并且设置IP白名单(ip请联系研发产品) 6. upload_ci.js 批量上传代码的命令脚本 ``` const path = require('path'); const upload = require(path.join(__dirname, 'destroy/upload.main.js')) ; ( async () => { try { const result = await upload.start(); console.log(`\n发布完成: 成功 ${result.success} 个, 失败 ${result.failed} 个`); } catch (e) { console.error('全局捕获错误:', e); } } )(); ``` 2. 其他配置项 ``` package.json (如果没有请新增) { "scripts": {"upload": "node upload_ci.js"} } ``` ## 注意事项: 1. 本项目中使用到小程序APPID等信息的文件 project.config.json和config.js ,建议项目中减少其他文件直接写死appid。 2. config.js文件中应用的当前appid的参数名改为“current_appid” ``` // @config 确定使用的小程序appid const current_appid = 'xxxxxxxxxxxxxxx'; ```