1. 背景
uniapp中采用vue-cli方式开发微信小程序,vscode(就是单纯的不想用HBuilderX开发,用着不顺)中每次启动完项目后都需要手动打开微信开发者工具,首次打开的时候还需导入项目,就想简化一下开发流程,把手动变为自动。并且更灵活的交给开发人员控制是否打开,是否跳过开发者工具的初始化耗时。下面分为两次优化。
2. Enquirer简单介绍
Stylish CLI prompts that are user-friendly, intuitive and easy to create.
用户友好的、简单易懂的、易于创建的交互式询问命令行界面
使用示例:
const { prompt } = require('enquirer');
const response = await prompt({
type: 'input',
name: 'username',
message: 'What is your username?'
});
console.log(response);
运行后,会看到问题,等待用户输入,输入haha后,会得到如下结果:
✔ What is your username? · haha
{ username: 'haha' }
3. 第一次优化:
3.1 打开微信开发者工具脚本
#!/usr/bin/env node
const path = require("path");
const os = require("os");
const { stat, mkdir } = require("fs");
const automator = require("miniprogram-automator");
const argv = process.argv.slice(2);
const rootDir = process.cwd();
// const pagesJson = require(path.resolve(__dirname, "../src/pages.json"));
console.log("platform:", os.platform());
console.log("miniprogram argv:", argv);
// 项目文件夹
const projectPath = path.resolve(rootDir, `./dist/${argv[0]}/mp-weixin`);
const cliPath =
os.platform() === "win32"
? "C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat"
: "/Applications/wechatwebdevtools.app/Contents/MacOS/cli";
function openMiniProgram() {
// developers.weixin.qq.com/miniprogram/dev/devtools/auto/automator.html
// cliPath 未设置时将会在以下几个位置尝试寻找:
// Mac:/Applications/wechatwebdevtools.app/Contents/MacOS/cli
// Win:C:/Program Files (x86)/Tencent/微信web开发者工具/cli.bat
automator
.launch({
// port: 49582,
cliPath: cliPath, // 工具 cli 位置,如果你没有更改过默认安装位置,可以忽略此项
// projectPath: `/Users/fangchaoqun/pro/net_hospital_minapp_web/dist/${argv[0]}/mp-weixin`, // 项目文件地址
projectPath: projectPath, // 项目文件地址
})
.then(async (miniProgram) => {
console.log("启动微信开发者工具中,请耐心等待...");
const page = await miniProgram.switchTab(`/pages/tabbar/home/home`);
// await page.waitFor(500);
// const element = await page.$(".kind-list-item-hd");
// console.log(await element.attribute("class"));
// await element.tap();
// await miniProgram.close();
console.log("启动微信开发者工具成功");
process.exit();
})
.catch((err) => {
console.log("微信开发者工具打开异常,请尝试手动打开项目");
console.error(err);
process.exit();
});
}
stat(projectPath, (err, stats) => {
if (err) {
console.log("文件夹不存在,即将创建");
mkdir(projectPath, { recursive: true }, (e) => {
if (e) throw e;
openMiniProgram();
});
return;
}
if (stats.isDirectory()) {
console.log("文件夹存在,直接打开");
openMiniProgram();
}
});
3.2 在package.json中配置命令
{
"scripts": {
"predev:mp-weixin": "echo -e '\u001b[32m项目启动后会自动打开微信开发者工具,如果自动打开失败,请手动打开开发者工具\u001b[0m' && node scripts/miniprogram.js dev",
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize --BASEURL_ENV=development",
"predev:mp-weixin:prod": "echo -e '\u001b[32m项目启动后会自动打开微信开发者工具,如果自动打开失败,请手动打开开发者工具\u001b[0m' && node scripts/miniprogram.js dev",
"dev:mp-weixin:prod": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize --BASEURL_ENV=production",
"build:mp-weixin:dev": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --BUILD_ENV=development",
"postbuild:mp-weixin:dev": "sh scripts/removeRTC.sh && node scripts/miniprogram.js build",
"build:mp-weixin:prod": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build --BUILD_ENV=production",
"postbuild:mp-weixin:prod": "sh scripts/removeRTC.sh && node scripts/miniprogram.js build",
}
}
3.3 总结
-
需求是满足了,在运行
npm run dev:mp-weixin后,是会自动打开微信开发者工具 -
但是打开微信开发者工具后,会加载很长时间,初始化那个项目,命令行就一直挂载等待着(项目一旦大了,这个过程真是漫长,还有跟你本地的电脑配置有关),等初始化结束了,才能继续执行后面的任务
3.4 需要优化改进的点
-
需不需要自动打开微信开发者工具,命令行中交给开发者选择,默认不需要,直接执行后面的任务
-
打开后,需不需要等待微信开发者工具的初始化任务完成,默认不需要,直接执行后面的任务
-
总体不够灵活,有时候需要自行打开,有时候不需要,由开发者决定
4. 第二次优化
4.1 改进后的打开微信开发者工具脚本
-
使用Enquirer增加交互提醒,开发人员可以选择是否自动打开微信开发者工具
-
并且增加了等待时间,在等待时间内如果开发者不执行操作,将执行默认操作
关于enquirer交互式确认选择,基本使用如下:
const { Confirm } = require('enquirer');
const prompt = new Confirm({
name: 'question',
message: 'Want to answer?'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
存在的难点
- 现在存在的问题是,如何在命令行中弹出问题,让用户选择的同时,还能动态的更改文字内容。一番文档查找,文档中有提供自定义交互式提示
- 动态文案解决了,现在还存在一个问题,就是给定等待时间结束后,命令不操作,就一直挂载着,没有继续执行后面的任务,需要开发者敲回车按键后才能继续执行后面任务,所以需要解决
解决:enquirer.use,写一个plugin,在给定的时间内,prompt.cancel()自动结束,释放命令行
#!/usr/bin/env node
const Enquirer = require("enquirer");
const {Prompt} = require("enquirer");
const chalk = require("chalk");
// ...
const WAIT_TIME = 5;
function openMiniProgram() {
// ...
}
// 检查目标文件夹是否存在
function handleDirState () {
// ...
}
// https://www.npmjs.com/package/enquirer#-custom-prompts
class HaiKarate extends Prompt {
constructor(options = {}) {
super(options);
this.count = options.count || 0;
// this.cursorHide();
this.timer = null;
this._resolve = null;
this.handleTimer();
}
handleTimer() {
this.timer = setInterval(() => {
if (this.count === 0) {
clearInterval(this.timer);
this.clear();
this.close();
// process.exit(0);
} else {
this.count--;
this.render();
}
}, 1000);
}
render() {
this.clear(); // clear previously rendered prompt from the terminal
this.write(`${this.state.message}${this.count}${this.state.message2}`);
}
close() {
super.close();
}
}
const enquirer = new Enquirer();
const prompt1 = new HaiKarate({
message: "是否自动打开微信开发者工具?",
message2: "秒后将自动关闭,后续如需请自行手动打开 y/N",
name: "answer",
count: WAIT_TIME,
type: "confirm",
initial: false,
});
enquirer.register('haikarate', HaiKarate);
// https://github.com/enquirer/enquirer/issues/273
// 关键在于这里,设置一个plugin给enquirer使用,超过时间,执行prompt.cancel()取消命令行挂载
const timeoutPlugin = (timeout = 30) => enquirer => {
enquirer.on('prompt', prompt => {
const t = setTimeout(() => {
prompt.hint = () => {
return `${WAIT_TIME}内任务未手动选择${prompt.name === "answer2" ? "Y/n" : "y/N"},已默认执行`;
};
prompt.cancel();
if(prompt.name === "answer2") {
setTimeout(() => process.exit(0), 1000);
}
}, timeout*1000);
prompt.on('submit', _ => clearTimeout(t));
prompt.on('cancel', _ => clearTimeout(t));
});
}
enquirer.use(timeoutPlugin(WAIT_TIME)); // timeout after 5s
async function run() {
try {
const r1 = await enquirer.prompt([
{type: 'haiKarate', ...prompt1.options}
]);
if(r1 && r1.answer) {
prompt1.timer && clearInterval(prompt1.timer);
prompt1.timer = null;
console.log(chalk.green("微信开发者工具打开中..."));
handleDirState();
const prompt2 = new HaiKarate({
message: '是否跳过等待微信开发者工具初始化?',
message2: "秒后将跳过 Y/n",
name: "answer2",
count: WAIT_TIME,
type: 'confirm',
initial: true,
});
const r2 = await enquirer.prompt([
{type: 'haiKarate', ...prompt2.options}
]);
if(r2.answer2) {
console.log(chalk.greenBright("已跳过等待微信开发者工具初始化,继续执行后面任务"));
process.exit(0);
} else {
prompt2.timer && clearInterval(prompt2.timer);
prompt2.timer = null;
console.log(chalk.bgBlue("请耐心等待微信开发者工具初始化完成"));
}
} else {
console.log(chalk.red("已取消,后续请自行手动打开微信开发者工具"));
process.exit(0);
}
} catch (error) {
console.error(error);
}
}
run();
4.2 改进后的scripts脚本命令
{
"scripts": {
"predev:mp-weixin": "node scripts/miniprogram.js dev",
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize --BASEURL_ENV=development",
"predev:mp-weixin:prod": "node scripts/miniprogram.js dev",
"dev:mp-weixin:prod": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize --BASEURL_ENV=production",
}
}
4.3 实际测试
4.3.1 第1个交互问题:“是否自动打开微信开发者工具?”
- 输入
y
npm run dev:mp-weixin
> predev:mp-weixin
> node scripts/miniprogram.js dev
platform==> darwin
miniprogram argv==> [ 'dev' ]
✔ 是否自动打开微信开发者工具? (y/N) · true
微信开发者工具打开中...
- 输入
n
npm run dev:mp-weixin
> predev:mp-weixin
> node scripts/miniprogram.js dev
platform==> darwin
miniprogram argv==> [ 'dev' ]
✔ 是否自动打开微信开发者工具? (y/N) · false
已取消,后续请自行手动打开微信开发者工具
- 默认不选择,让其超时
npm run dev:mp-weixin
> predev:mp-weixin
> node scripts/miniprogram.js dev
platform==> darwin
miniprogram argv==> [ 'dev' ]
✖ 是否自动打开微信开发者工具? (y/N) · false 5内任务未手动选择y/N,已默认执行
4.3.2 第2个交互问题:“是否跳过等待微信开发者工具初始化?”
第1个问题输入了y后,才能进入第2个问题
- 输入
y
npm run dev:mp-weixin
> predev:mp-weixin
> node scripts/miniprogram.js dev
platform==> darwin
miniprogram argv==> [ 'dev' ]
✔ 是否自动打开微信开发者工具? (y/N) · true
微信开发者工具打开中...
? 是否跳过等待微信开发者工具初始化? (Y/n) › 文件夹存在,直接打开
✔ 是否跳过等待微信开发者工具初始化? (Y/n) · true
已跳过等待微信开发者工具初始化,继续执行后面任务
- 输入
n
npm run dev:mp-weixin
> predev:mp-weixin
> node scripts/miniprogram.js dev
platform==> darwin
miniprogram argv==> [ 'dev' ]
✔ 是否自动打开微信开发者工具? (y/N) · true
微信开发者工具打开中...
? 是否跳过等待微信开发者工具初始化? (Y/n) › 文件夹存在,直接打开
✔ 是否跳过等待微信开发者工具初始化? (Y/n) · false
请耐心等待微信开发者工具初始化完成
- 默认不选择,让其超时
npm run dev:mp-weixin
> predev:mp-weixin
> node scripts/miniprogram.js dev
platform==> darwin
miniprogram argv==> [ 'dev' ]
✔ 是否自动打开微信开发者工具? (y/N) · true
微信开发者工具打开中...
? 是否跳过等待微信开发者工具初始化? (Y/n) › 文件夹存在,直接打开
✖ 是否跳过等待微信开发者工具初始化? (Y/n) · true 5内任务未手动选择Y/n,已默认执行
是否跳过等待微信开发者工具初始化?0秒后将跳过 Y/n
4.3.3 总结
这样就很灵活的解决了上述痛点,再也不需要长时间等待微信开发者初始化卡在那了
5. 参考资料
6. 最后
如果文章对您有帮助,可以关注我的个人公众号半个柠檬2020,偶尔也会在公众号上面更新一些自己的学习笔记。