在最近的工作中,主要做的是C端的小程序,在开发过程中倒是还好,一到改BUG的时候,可能就会进入保存,编译,自动预览的循环了,虽然微信已经提供了快简介自动预览,但是总归是一个手动的过程,要是能监听文件变化自 ...
在最近的工作中,主要做的是C端的小程序,在开发过程中倒是还好,一到改BUG的时候,可能就会进入保存,编译,自动预览的循环了,虽然微信已经提供了快简介自动预览,但是总归是一个手动的过程,要是能监听文件变化自动预览不是更好吗? 查看文档于是我就去看了下文档,发现微信已经提供了这个API,可以用命令行调用,也可以用HTTP调用。 一开始本着配置少一点的原则,我选择了HTTP调用,因为命令行调用需要配置微信开发者工具的安装目录,而HTTP调用可以通过微信指定的路径获取端口号(实践证明,too young, too simple, 认真你就输了, HTTP调用的问题太多,所以我后来又改成了命令行调用 )。 然后就去官方所指示的ide文件夹找端口号了,结果并没有发现那个文件。怎么回事呢?一顿搜索之后,才知道目前的版本需要如下才能开启http服务: 微信开发者工具 -> 查看所有项目 -> 设置 -> 安全 ,里面有个服务端口,选择开启以后就能找到ide文件,进而得到端口号进行后续操作了。 前置工作
读取端口号文档中提到 端口号文件位置: macOS : ~/Library/Application Support/微信开发者工具/Default/.ide Windows : ~/AppData/Local/微信开发者工具/User Data/Default/.ide 既然路径有了,那么就好说了,只要 获取到用户目录,然后再拼接上不同平台的后续路径,那么通过读取.ide文件就可以得到端口号了 。 代码如下: const fs = require("fs");
const os = require("os");
const isWin = os.platform() === `win32`;
function getHttpPort() {
const home = os.homedir();
const suffix = isWin
? `/AppData/Local/微信开发者工具/User Data/Default/.ide`
: `/Library/Application Support/微信开发者工具/Default/.ide`;
const idePath = home + suffix;
const port = fs.readFileSync(idePath, { encoding: "utf8" });
return port;
}
复制代码 打开工具或指定项目HTTP调用实例: # 打开工具
http://127.0.0.1:端口号/open
# 打开/刷新项目
http://127.0.0.1:端口号/open?projectpath=项目全路径
复制代码 先在浏览器中直接进行访问,很好,你会发现 微信开发者工具并没有打开 ,再仔细看了下文档,用法肯定没错的,总共就端口号和项目路径两个变量,怎么可能会出错呢?被某厂坑久了,就知道有问题是必然的。 算了,打不开就打不开吧,影响并不是很大,反正平时开发的时候,开发者工具都是打开的。这个问题呢,我猜测是因为 工具每次打开端口号都会变化 ,而读取的端口号是之前的,所以就没用了。 命令行调用-o, --open [projectpath]: 打开工具,如果不带 projectpath,只是打开工具。如果带 project path,则打开路径中的项目,每次执行都会自动编译刷新,并且自动打开模拟器和调试器。projectpath 不能是相对路径。项目路径中必须含正确格式的 project.config.json 且其中有 appid 和 projectname 字段。 调用: cli -o /Users/username/demo
复制代码 这次的调用完全没有问题的。 自动预览HTTP调用接口定义: URL:/autopreview HTTP 方法:GET
这个接口请求以后,倒是可以用,但是坑也不小。
文档总是缺三少四的,这里一块那里一块,稍微看漏一点这个功能可能就出不来了,说到底看文档就是得仔细。 命令行调用自动预览必须处于登录状态,如果没有登录,会提示需先登录。
官方文档只介绍了这两个参数,还是像之前一样,从预览那个的调用凑一下吧。
用命令行测试: cli --auto-preview /Users/username/demo --compile-condition {\"pathName\": \"pages/home/index\",\"query\":\"a=1\"}
复制代码 大坑
node脚本编写思路辅助函数// 将D:\\www\\soft转换成D:/www/soft这种形式
// msg为路径不存在时的报错信息
function getPath(projectpath, msg) {
if (!projectpath) {
throw new Error(msg);
}
return projectpath.split(path.sep).join(`/`);
}
// 获取打包路径
function getDist(config = {}) {
const { projectpath } = config;
return (
config.dist ||
(/dist\/?$/.test(projectpath) ? projectpath : (projectpath || "") + `/dist`)
);
}
// 将exec转为promise类型的函数,方便使用async await
const promisify = require("util").promisify;
let { exec } = require("child_process");
exec = promisify(exec);
复制代码 这里介绍一下exec child_process.exec(command[, options][, callback])
复制代码
spawn和exec的却别在于,spawn的输出是实时的,而exec是执行完之后统一返回。前者还得监听事件略显麻烦,所以我选择了exec。 open.jsasync function open({ projectpath, cli, }) {
return new Promise(async (resolve, reject) => {
log();
log(chalk.green(`打开开发者工具中...`));
const result = await exec(
`cli -o ${projectpath}`,
{
cwd: cli
}
);
const isSuccess = result.stdout;
log(isSuccess ? chalk.green(`打开成功`) : chalk.red(`打开失败`));
isSuccess ? resolve() : reject();
})
}
复制代码 preview.jsasync function preview(config) {
await open(config);
const port = getHttpPort();
const { dist, projectpath, time, compile, cli } = config;
log();
log(chalk.blue(`开始监听文件变动`));
log(`路径参数: `, compile);
fs.watch(
dist,
debounce(async (evt, filename) => {
log();
console.log(`${filename} ${evt}`);
log(chalk.green(`自动预览重启中...`));
log(
`执行命令: cli --auto-preview ${projectpath} --compile-condition ${compile}`
);
const result = await exec(
`cli --auto-preview ${projectpath} --compile-condition ${compile}`,
{
cwd: cli
}
);
const isSuccess = result.stdout;
log(isSuccess ? chalk.green(`自动预览成功`) : chalk.red(`自动预览失败`));
}, time || 1000)
);
}
复制代码 lib/index.jsconst fn = {
preview,
upload,
};
function run(config, type) {
if (!fn[type]) {
throw new Error(`type参数不合法,请确保为preview, upload的一种`);
}
log(chalk.green(`本次启动类型为: ${type}`));
fn[type](config);
}
复制代码 config参数从命令行参数中读取文件获得,type参数为命令行参数。 bin/index.js#! /usr/bin/env node
const run = require("../lib/index");
const program = require("commander");
const fs = require("fs");
const path = require("path");
const { getPath, getHttpPort, getDist } = require("../util/index");
program
.option("-c, --config <type>", "config file", "auto.js")
.option("-t, --type <type>", "auto type, etc: preview, upload", "preview")
.parse(process.argv);
// 获取执行命令时所在的目录,拼接上配置文件目录,使用require(ConfigFile)即可获得相关配置
const CD = process.cwd();
const Config = program.config;
const ConfigFile = path.join(CD, Config);
const defaultCompile = {
pathName: `pages/home/index`
};
// 判断配置文件不存在,则直接报错
if (!fs.existsSync(ConfigFile)) {
throw new Error(`[ERROR]: ${Config} not found in ${CD}`);
} else {
start();
}
function start() {
let config = require(ConfigFile);
config = { ...config };
config.projectpath = getPath(
config.projectpath,
`配置文件中projectPath字段必须有值`
);
const projectpath = config.projectpath;
config.dist = getDist(config);
config.compile = JSON.stringify(config.compile || defaultCompile).replace(
/\"/g,
`\\"`
);
// 这里可写可不写,打开工具后会进行再次获取
config.port = getHttpPort();
run(config, program.type);
}
复制代码 至此,该功能已经大致完成了,我已经上传到了npm,可以直接进行使用。 wx-auto微信开发者工具,HTTP调用,自动预览,提高工作效率 局部安装npm i wx-auto -D 或者 yarn add wx-auto -D
复制代码 全局安装npm i wx-auto -g
复制代码 使用方法wxauto
或者
wxauto -t preview -c auto.js
复制代码 参数(均有默认值)-t, --type 类型,目前支持preview和upload
-c, --config 配置文件名,默认值为auto.js
复制代码 文件路径为相对路径,相对于执行命令时所在的路径 配置文件{
cli: "D:/soft/微信web开发者工具", // cli文件所在的目录
projectpath: `D:/www/react/heywoof-app-frontend`, // 项目地址
compile: {
pathName: `pages/scene/index`, // 自动预览的页面路径
query: `activityId=5d45050569515b000c5b740a` // 查询参数,微信目前有BUG,只能识别一个参数
},
build: `yarn build-test:weapp`, // 上传之前需要执行的命令
upload: {
version: "1.0.1",
desc: "测试自动上传,不要乱动"
}
};
复制代码 此外还包含了自动打包上传的功能,配置之后执行 自动化测试在查看文档的时候,我发现微信官方推出了一个 多端统一开发工具——kbone ,这个是基于vue的,就是配置略显麻烦。 除此之外,微信小程序现在已经支持自动化测试了,感兴趣的小伙伴可以自行尝试。注意: 该功能需要最新版本支持 ,一定要符合文档所说的版本,我简单尝试了一下,自动化是可以实现的,更具体的测试就得看工作需要了。 |