30多个小程序一键发布——miniprogram-ci

概述

miniprogram-ci 是从微信开发者工具中抽离的关于小程序/小游戏项目代码的编译模块。

开发者可不打开小程序开发者工具,独立使用 miniprogram-ci 进行小程序代码的上传、预览等操作。

miniprogram-ci 从 1.0.28 开始支持第三方平台开发的上传和预览,调用方式与普通开发模式无异。查看详情

密钥及 IP 白名单配置

使用 miniprogram-ci 前应访问"微信公众平台-开发-开发设置"后下载代码上传密钥,并配置 IP 白名单 开发者可选择打开 IP 白名单,打开后只有白名单中的 IP 才能调用相关接口。我们建议所有开发者默认开启这个选项,降低风险 代码上传密钥拥有预览、上传代码的权限,密钥不会明文存储在微信公众平台上,一旦遗失必须重置,请开发者妥善保管

入口

功能

miniprogram-ci 目前提供以下能力:

  1. 上传代码,对应小程序开发者工具的上传
  2. 预览代码,对应小程序开发者工具的预览
  3. 构建 npm,对应小程序开发者工具的: 菜单-工具-构建npm
  4. 上传云开发云函数代码,对应小程序开发者工具的上传云函数能力
  5. 上传云托管代码,对应小程序开发者工具的上传云托管能力
  6. 上传云存储/静态托管文件,对应小程序开发者工具-云开发-云存储和静态托管文件管理
  7. 代理,配置 miniprogram-ci 的网络请求代理方式
  8. 支持获取最近上传版本的 sourceMap
  9. 支持 node 脚本调用方式和 命令行 调用方式

脚本调用

npm install miniprogram-ci --save

代码

preview.js

const ci = require('miniprogram-ci');
const fs = require('fs');
const path = require('path');
let config = {xcxKey: [], //需要上传的小程序列表version: "", //版本号desc: "", //备注appindex: 0 //当前执行到第几个
}exports.start = async () => {//先拿到需要上传的列表,也就是小程序的appid和名称等相关信息,还有上传的版本和备注fs.readFile(path.join(__dirname, '../xcxkey/xcxkey.json'),'utf-8',(err, data) => {const fileJson = JSON.parse(data)config.xcxKey = fileJson.xcxKey;config.version = fileJson.version;config.desc = fileJson.desc;config.env = fileJson.env;config.appindex = 0;console.log(`本次提交--${config.xcxKey.map(item=> config.env + item.desc + config.desc)}`);console.log(`版本--${config.version}`);previewStart();});}const previewStart = async () => {if (!config.xcxKey[config.appindex]) {console.log('上传完成')return;}//开始上传,首先修改文件信息await setProjectConfig();await setMain();console.log(`${config.xcxKey[config.appindex].desc}--${config.env}开始`);const project = new ci.Project({appid: config.xcxKey[config.appindex].appid,type: 'miniProgram',projectPath: path.resolve(__dirname, '../unpackage/dist/dev/mp-weixin'),privateKeyPath: path.resolve(__dirname,`../xcxkey/private.${config.xcxKey[config.appindex].appid}.key`),ignores: ['node_modules/**/*'],});// 预览const uploadResult = await ci.preview({project,version: config.xcxKey[config.appindex].version,desc: `${config.env}——${config.desc}`,setting: {es6: true,minifyJS: true,minifyWXML: true,minifyWXSS: true,minify: true},qrcodeFormat: 'image',qrcodeOutputDest: path.resolve(__dirname, `../ci/preview-images/${config.xcxKey[config.appindex].title}.jpg`),onProgressUpdate: getstate,pagePath: 'pages/home/index', // 预览页面searchQuery: ''  // 预览参数 [注意!]这里的`&`字符在命令行中应写成转义字符`\&`});//监听上传过程,如果上传完成延迟10秒再上传下一个function getstate(e) {console.log('eeee', e);if (e._status === "done" && e._msg === "upload") {console.log(`${config.xcxKey[config.appindex].desc}--${config.env}上传完成`)setTimeout(() => {config.appindex += 1;previewStart();}, 1000)}}
}//修改 project.config.json 内容
const setProjectConfig = async () => {// 要读取和替换的文件路径const project_config = '../unpackage/dist/dev/mp-weixin/project.config.json';const promise = new Promise((resolve, reject) => {// 读取 project.config.jsonfs.readFile(path.join(__dirname, project_config),'utf8',(err, data) => {if (err) throw err;let json = JSON.parse(data);// 替换 appid 和 projectnamejson.appid = config.xcxKey[config.appindex].appid;json.projectname = config.xcxKey[config.appindex].name;// 改写 project.config.json 中 appid 和 projectnamefs.writeFile(path.join(__dirname, project_config),JSON.stringify(json, null, 4),(err) => {if (err) throw err;resolve();});});});return promise;
}//修改 main.js 内容
const setMain = async () => {// 要读取和替换的文件路径const app_main_file = '../unpackage/dist/dev/mp-weixin/common/main.js';const promise = new Promise((resolve, reject) => {// 读取 unpackage/dist/dev/mp-weixin/common/main.jsfs.readFile(path.join(__dirname, app_main_file),'utf8',(err, data) => {if (err) throw err;let app_main = data;const hotel_id = config.xcxKey[config.appindex].hotel_id;// 替换 source_hotel_idlet re = /(?<=source_hotel_id:").*?(?=",source_hotel_id_end_ci:)/;app_main = app_main.replace(re, hotel_id);// 改写 unpackage/dist/dev/mp-weixin/common/main.js 中 source_hotel_idfs.writeFile(path.join(__dirname, app_main_file),app_main,(err) => {if (err) throw err;resolve();});});});return promise;
}

upload.js

const ci = require('miniprogram-ci');
const fs = require('fs');
const path = require('path');
let config = {xcxKey: [], //需要上传的小程序列表version: "", //版本号desc: "", //备注env: "",appindex: 0 //当前执行到第几个
}exports.start = async () => {//先拿到需要上传的列表,也就是小程序的appid和名称等相关信息,还有上传的版本和备注fs.readFile(path.join(__dirname, '../xcxkey/xcxkey.json'),'utf-8',(err, data) => {const fileJson = JSON.parse(data)console.log(fileJson);config.xcxKey = fileJson.xcxKey;config.version = fileJson.version;config.desc = fileJson.desc;config.env = fileJson.env;config.appindex = 0;console.log(`本次提交--${config.xcxKey.map(item=> config.env + item.desc)} --- config.desc`);console.log(`版本--${config.version}`);uploadStart();});}const uploadStart = async () => {if (!config.xcxKey[config.appindex]) {console.log('上传完成')return;}//开始上传,首先修改文件信息await setProjectConfig();await setMain();console.log(`${config.xcxKey[config.appindex].desc}--${config.env}开始`);const project = new ci.Project({appid: config.xcxKey[config.appindex].appid,type: 'miniProgram',projectPath: path.resolve(__dirname, '../unpackage/dist/dev/mp-weixin'),privateKeyPath: path.resolve(__dirname,`../xcxkey/private.${config.xcxKey[config.appindex].appid}.key`),ignores: ['node_modules/**/*'],});// 上传const uploadResult = await ci.upload({project,version: config.xcxKey[config.appindex].version,desc: `${config.env}——${config.desc}`,setting: {es6: true,minifyJS: true,minifyWXML: true,minifyWXSS: true,minify: true},onProgressUpdate: getstate,});console.log(uploadResult)//监听上传过程,如果上传完成延迟10秒再上传下一个function getstate(e) {if (e._status == "done" && e._msg == "upload") {console.log(`${config.xcxKey[config.appindex].desc}--${config.env}上传完成`)setTimeout(() => {config.appindex += 1;uploadStart();}, 1000)}}
}//修改 ext.json 内容
const setExtConfig = async () => {// 要读取和替换的文件路径const project_config = '../ext.json';const promise = new Promise((resolve, reject) => {// 读取 project.config.jsonfs.readFile(path.join(__dirname, project_config),'utf8',(err, data) => {if (err) throw err;let json = JSON.parse(data);// 替换 appid 和 projectnamejson.extAppid = config.xcxKey[config.appindex].appid;// 改写 project.config.json 中 appid 和 projectnamefs.writeFile(path.join(__dirname, project_config),JSON.stringify(json, null, 4),(err) => {if (err) throw err;resolve();});});});return promise;
}//修改 project.config.json 内容
const setProjectConfig = async () => {// 要读取和替换的文件路径const project_config = '../unpackage/dist/dev/mp-weixin/project.config.json';const promise = new Promise((resolve, reject) => {// 读取 project.config.jsonfs.readFile(path.join(__dirname, project_config),'utf8',(err, data) => {if (err) throw err;let json = JSON.parse(data);// 替换 appid 和 projectnamejson.appid = config.xcxKey[config.appindex].appid;json.projectname = config.xcxKey[config.appindex].name;// 改写 project.config.json 中 appid 和 projectnamefs.writeFile(path.join(__dirname, project_config),JSON.stringify(json, null, 4),(err) => {if (err) throw err;resolve();});});});return promise;
}//修改 main.js 内容
const setMain = async () => {// 要读取和替换的文件路径const app_main_file = '../unpackage/dist/dev/mp-weixin/common/main.js';const promise = new Promise((resolve, reject) => {// 读取 unpackage/dist/dev/mp-weixin/common/main.jsfs.readFile(path.join(__dirname, app_main_file),'utf8',(err, data) => {if (err) throw err;let app_main = data;const hotel_id = config.xcxKey[config.appindex].hotel_id;// 替换 source_hotel_idlet re = /(?<=source_hotel_id:").*?(?=",source_hotel_id_end_ci:)/;app_main = app_main.replace(re, hotel_id);// 改写 unpackage/dist/dev/mp-weixin/common/main.js 中 source_hotel_idfs.writeFile(path.join(__dirname, app_main_file),app_main,(err) => {if (err) throw err;resolve();});});});return promise;
}

package.json

{"scripts": {"upload": "node upload-ci.js","preview": "node preview-ci.js"},"dependencies": {"gulp": "^4.0.2","miniprogram-ci": "^1.8.12"}
}

在这里插入图片描述

preview-ci.js


const path = require('path');
const preview = require(path.join(__dirname, './ci/preview'));
;
(async () => {preview.start();})()

upload-ci.js


const path = require('path');
const upload = require(path.join(__dirname, './ci/upload'));
;
(async () => {upload.start();})()

在这里插入图片描述

{"xcxKey": [{"name": "名称","title": "title","appid": "appid","version": "1.0.0","desc": "备注"},...],"env": "正式环境","desc": "备注","version": "1.0.0"
}
// npm run preview(会把xcxkey中的所有小程序打包预览)
// npm run upload(会把xcxkey中的所有小程序打包提交体验版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/20684.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter底部导航BottomNavigationBar

Flutter底部导航BottomNavigationBar 主要代码&#xff1a; bottomNavigationBar: BottomNavigationBar(//选中菜单颜色fixedColor: Colors.red,//图标大小&#xff0c;默认24.0iconSize: 30,//第几个菜单选中currentIndex: currentIndex,//当item数量大于3个时需要设置type属…

simulink 结构体 bus creator

目录 结构体创建 bus creator 结构体引用Bus Selector 结构体赋值Bus Assignment 结构体对象 Bus 结构体数组打包Vector Concatenate 结构体数据存文件 结构体创建 bus creator 结构体引用Bus Selector 结构体赋值Bus Assignment 结构体对象 Bus 结构体数组打包Vector Co…

方便的记事本app有哪些 快捷方便的生活记事软件推荐

生活中很多时候都需要记事&#xff0c;比如去超市要买的物品清单&#xff0c;旅行时遇到的好看的风景、有趣的事情&#xff0c;以及脑海中不经意间产生的灵感、想法或思考感悟等&#xff0c;都可以随手用记事App软件记录下来&#xff0c;以便后续查看。那方便的记事本app有哪些…

计算机网络-网络层上篇

目录 一、网络层概述 二、网络层提供的两种服务 &#xff08;一&#xff09;面向连接的虚电路服务 &#xff08;二&#xff09;无连接的数据报服务 &#xff08;三&#xff09;虚电路服务与数据报服务的比较 三、IPv4地址及其应用 &#xff08;一&#xff09;IPv4地址概…

构建WebRTC技术需要的后端服务

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不是…

JS相关介绍

1.JS引入&#xff1a; 内部&#xff1a;直接在html文件内部使用script标签调用 外部&#xff1a;另外新建JS文件&#xff0c;再在html文件中调用 2.输入输出&#xff1a; 输入&#xff1a;prompt(请输入您的姓名&#xff1a;) 输出&#xff1a;document.write(你们真是天才) 注…

Nginx代理nginx.conf配置——反向代理(对WebSocket支持)

一、需求说明 基于Nginx代理nginx.conf配置——反向代理&#xff0c;如果要添加websocket支持&#xff0c;需要进行如下配置 二、配置内容 在http中添加一下配置&#xff0c;添加对websocket支持 http {# 配置其它内容map $http_upgrade $connection_upgrade {default upgra…

开心档之CSS 测验

目录 CSS 测验 CSS 测验 CSS测验是一种衡量前端开发人员对CSS的熟练程度的测试。通过CSS测验&#xff0c;可以评估一个人对CSS语言的掌握程度和应用能力&#xff0c;帮助公司或招聘方挑选合适的人才。下面将介绍如何进行CSS测验以及一些常见的CSS考题。 一、CSS测验的类型 1…

GaussDB WDR报告分析

标题 问题描述问题现象告警业务影响原因分析处理方法步骤 1步骤 2步骤 3步骤 4步骤 6步骤 7步骤 8步骤9步骤 10步骤 11步骤 12 问题描述 CPU使用率高。 问题现象 出现CPU使用率超过阈值&#xff0c;CPU使用率快速上涨或短时间持续较高水平等现象。 告警 CPU使用率告警。 …

Redis学习(二)线程安全、分布式锁、消息队列

文章目录 优惠券秒杀全局ID生成器优惠券秒杀下单超卖问题一人一单 分布式锁基于Redis的setnx指令实现分布式锁解决锁误删问题基于Lua脚本实现多条指令原子性Redis调用Lua脚本Java中使用Lua脚本 RedissonRedisson快速入门Redisson可重入锁原理Redisson的锁重试和Watchdog机制Red…

Unity物理相关组件——2D关节

一&#xff1a;前言 关节组件用来模拟物体与物体之间的连接关系&#xff0c;必须依赖于刚体组件 二&#xff1a;Hinge Joint 2D 用于实现链条物体、钟摆等物体的模拟 ——Enable Collision&#xff1a;是否开启碰撞 ——Connected Rigid Body&#xff1a;关联的刚体&#xff0…

JVM理论(三)运行时数据区--PC寄存器/虚拟机栈/本地方法栈

运行时数据区(JVM内存结构) JVM内存结构 内存是非常重要的资源,是硬盘和CPU的中间桥梁,承载操作系统和应用程序的实时运行.JVM内存布局规定java在运行过程中内存申请、分配、管理的策略&#xff0c;保证JVM高效稳定运行。不同的JVM对于内存划分和管理机制存在部分差异(如J9和JR…