在最近的工做中,主要作的是C端的小程序,在开发过程当中却是还好,一到改BUG的时候,可能就会进入保存,编译,自动预览的循环了,虽然微信已经提供了快简介自动预览,可是总归是一个手动的过程,要是能监听文件变化自动预览不是更好吗?javascript
因而我就去看了下文档,发现微信已经提供了这个API,能够用命令行调用,也能够用HTTP调用。html
一开始本着配置少一点的原则,我选择了HTTP调用,由于命令行调用须要配置微信开发者工具的安装目录,而HTTP调用能够经过微信指定的路径获取端口号(实践证实,too young, too simple, 认真你就输了,HTTP调用的问题太多,因此我后来又改为了命令行调用)。vue
而后就去官方所指示的ide文件夹找端口号了,结果并无发现那个文件。怎么回事呢?一顿搜索以后,才知道目前的版本须要以下才能开启http服务: 微信开发者工具 -> 查看全部项目 -> 设置 -> 安全,里面有个服务端口,选择开启之后就能找到ide文件,进而获得端口号进行后续操做了。java
fs.watch
进行目录和文件的监听,在文件变更后调用自动预览文档中提到 端口号文件位置:node
macOS : ~/Library/Application Support/微信开发者工具/Default/.ide Windows : ~/AppData/Local/微信开发者工具/User Data/Default/.idereact
既然路径有了,那么就好说了,只要获取到用户目录,而后再拼接上不一样平台的后续路径,那么经过读取.ide文件就能够获得端口号了。ios
代码以下:git
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;
}
复制代码
实例:github
# 打开工具
http://127.0.0.1:端口号/open
# 打开/刷新项目
http://127.0.0.1:端口号/open?projectpath=项目全路径
复制代码
先在浏览器中直接进行访问,很好,你会发现微信开发者工具并无打开,再仔细看了下文档,用法确定没错的,总共就端口号和项目路径两个变量,怎么可能会出错呢?被某厂坑久了,就知道有问题是必然的。web
算了,打不开就打不开吧,影响并非很大,反正平时开发的时候,开发者工具都是打开的。这个问题呢,我猜想是由于工具每次打开端口号都会变化,而读取的端口号是以前的,因此就没用了。
-o, --open [projectpath]: 打开工具,若是不带 projectpath,只是打开工具。若是带 project path,则打开路径中的项目,每次执行都会自动编译刷新,而且自动打开模拟器和调试器。projectpath 不能是相对路径。项目路径中必须含正确格式的 project.config.json 且其中有 appid 和 projectname 字段。
调用:
cli -o /Users/username/demo
复制代码
此次的调用彻底没有问题的。
接口定义:
URL:/autopreview
HTTP 方法:GET
URL 参数 | 必填 | 说明 |
---|---|---|
projectpath | 是 | 指定路径中的项目。如项目已打开,自动刷新项目。如项目未建立,自动建立并自动预览项目 |
infooutput | 否 | 指定后,会将本次自动预览的额外信息以 json 格式输出至指定路径,如代码包大小、分包大小信息。 |
compilecondition | 否 | 指定自定义编译条件,值为 json 字符串,条件可指定两个字段,pathName 表示打开的页面,不填表示首页,query 表示页面参数 |
这个接口请求之后,却是能够用,可是坑也不小。
文档老是缺三少四的,这里一块那里一块,稍微看漏一点这个功能可能就出不来了,说到底看文档就是得仔细。
自动预览必须处于登陆状态,若是没有登陆,会提示需先登陆。
--auto-preview <project_root>
: 自动预览代码,project_root 指定项目根路径。
--auto-preview-info-output <path>
: 指定后,会将本次预览的额外信息以 json 格式输出至指定路径,如代码包大小、分包大小信息。
--compile-condition '<json>'
: 指定自定义编译条件,json 条件可指定两个字段,pathName 表示打开的页面,不填表示首页,query 表示页面参数
用命令行测试:
cli --auto-preview /Users/username/demo --compile-condition {\"pathName\": \"pages/home/index\",\"query\":\"a=1\"}
复制代码
JSON.stringify(obj).replace(/\"/g, `\\"`)
所得到的字符串,注意要把"换成\",且先后不须要单引号,文档里面那种调用方式会报错,不信的小伙伴能够本身尝试。// 将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])
复制代码
参数 | 类型 | 说明 |
---|---|---|
command | string | The command to run, with space-separated arguments. (须要运行的命令,参数用空格分开) |
options | object | { cwd: "子进程工做目录,默认为null", } 其余参数我没怎么用过 |
callback | 否 | 回调函数: (error: Error, stdout: string | Buffer, stderr: string | Buffer) |
spawn和exec的却别在于,spawn的输出是实时的,而exec是执行完以后统一返回。前者还得监听事件略显麻烦,因此我选择了exec。
async 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();
})
}
复制代码
async 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)
);
}
复制代码
const 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参数为命令行参数。
#! /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,能够直接进行使用。
微信开发者工具,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: "测试自动上传,不要乱动"
}
};
复制代码
此外还包含了自动打包上传的功能,配置以后执行wxauto -t upload -c auto.js
,上传完毕后就会自动打开微信公众平台登陆的网站,我的感受仍是挺实用的。
在查看文档的时候,我发现微信官方推出了一个多端统一开发工具——kbone,这个是基于vue的,就是配置略显麻烦。
除此以外,微信小程序如今已经支持自动化测试了,感兴趣的小伙伴能够自行尝试。注意:该功能须要最新版本支持,必定要符合文档所说的版本,我简单尝试了一下,自动化是能够实现的,更具体的测试就得看工做须要了。