.btn{width:90%!important;边距:30px自动30px自动;}.code{显示:flex;对齐项目:居中;弹性方向:列;.code-img{宽度:300px;高度:300px;}}}需要开发小程序的朋友随时都会听到一句话:“哎,快给我一个xxx环境的预览代码”,不管你在做什么,你必须快速回复:“稍等,我给你编码……”然后你搭建了一个xxx环境包,打开微信开发者工具,点击预览,稍等片刻,预览代码就出来了,您复制并扔给您的父亲。终于有一天,当你正专心做一件不可描述的事情时,“喂,给我一份xxx环境的预览代码”,此时你在心里怒吼:“我不给你打码了!你自己敲吧!”!”于是就有了这个需求,做一个让爸爸们独立打码的东西,嗯,应该只有一个按钮,点击预览二维码,应该是这样的:没有错!去做就对了!计划做大事始于胡思乱想。下面我们来想一想,要实现这个功能需要做哪些准备工作。找到微信开发者工具的接口,最重要的就是看微信开发者工具有没有给我们提供这样的接口,让我们进行操作。查阅文档后,我们会发现确实有!https://developers.weixin.qq...你会发现文档给我们提供了两种接口,命令行调用和HTTP调用。有了界面,一切都好办。无非就是调整界面,获取二维码,粘贴到页面上。这很简单。梳理一下开发过程,我们用一张流程图来说明这个简单的事情:https://www.processon.com/vie...所需要的技术工欲善其事必先利其器。我们要做这个事情,还是先梳理一下用到的技术。微信开发者工具是一个小程序项目(这里以一个mpvue项目为例)前端vue+vux,这里前端没什么可做的,这种搭配纯粹是因为已经在做前端了移动端,直接使用。后端koa2,当然后端什么都可以用。我这里选择koa2,纯粹是因为我没用别的……前后端HTTP请求都是用axios的。涉及到节点操作,命令行需要用到shelljs。好像没有别的东西了,用到时候再说吧。卷起袖子,从后端开始。为了省事,把前后端的东西放在一起。项目目录:可以看到后端的东西都放在了server目录下。server/index.js首先看入口文件index.js。从这里我们可以知道后端需要做两件事。首先,它必须能够访问前端构建的静态资源。其次,它必须能够通过HTTP接口与前端通信。相互影响。见代码:constpath=require('path')constKoa=require('koa')constkoaStatic=require('koa-static')constbodyParser=require('koa-bodyparser')constrouter=require('./router')constapp=newKoa()constport=9871app.use(bodyParser())//处理静态资源这里是前端搭建好后的目录app.use(koaStatic(path.resolve(__dirname,'../dist')))//路由处理接口app.use(router.routes()).use(router.allowedMethods())//监听端口app.listen(9871)console.log(`[demo]start-quick是从${port}端口开始的`)对于静态资源,使用koa-static。关键是如何给前端提供接口,这取决于路由。server/router/index.jsconstRouter=require('koa-router')//业务逻辑constwx=require('../controller/wx')constrouter=newRouter({//接口前缀如open接口请求路径为/api/openprefix:'/api'})router.get('/open',wx.open).get('/login',wx.login).get('/preview',wx.preview).get('/build',wx.build)module.exports=router这里可以清楚的看到后端提供了四个接口,但是每个接口的业务逻辑都封装在controller中的wx.js中。以后如果有其他业务逻辑,只需要在controller中添加相应的模块即可。server/controller/wx.js//微信开发者工具接口调用逻辑const{open,login,preview,build}=require('../utli/wxToolApi')//处理成功失败返回格式const{successBody,errorBody}=require('../utli')classWxController{/***根据环境打包mpvue工程*@returns{Promise}*/staticasyncbuild(ctx){//passedfrom前端获取参数constquery=ctx.request.queryif(!query||!query.env){ctx.body=errorBody(null,'构建项目失败')return}const[err,data]=awaitbuild(query.env)ctx.body=错误?errorBody(err,'构建项目失败'):successBody(data,'构建项目成功')}/***打开微信开发者工具*@returns{Promise}*/staticasyncopen(ctx){const[err,data]=awaitopen()ctx.body=err?errorBody(err,'打开微信开发者工具失败'):successBody(data,'打开微信开发者工具成功')}/***登录微信开发者工具*@returns{Promise}*/staticasynclogin(ctx){const[err,data]=awaitlogin()ctx.body=err?errorBody(err,'登录二维码返回失败'):successBody(data,'登录2维码返回成功')}/***查看预览代码*@returns{Promise}*/staticasyncpreview(ctx){const[err,data]=awaitpreview()ctx.body=err?errorBody(err,'预览二维码返回失败'):successBody(data,'预览二维码返回成功')}}module.exports=WxController为了让代码更清晰,这里给出具体操作的接口逻辑微信开发者工具去util/wxToolApi.js,只是处理如何以统一的格式返回给前端util/wxToolApi.jsconst{promiseWrap,successBody,errorBody}=require('../utli')const{INSTALL_PATH,PROJECT_PATH,PORT_PATH,PORT_FILE_NAME,HOST}=require('../const')const{readFile}=要求('../utli/nodeApi')constshell=require('shelljs')constaxios=require('axios')module.exports={/***根据环境打包mpvue项目*@paramenv[doc,pre,prd]*@returns{*}*/build(env){returnpromiseWrap(newPromise((resolve,reject)=>{//进入项目目录shell.cd(PROJECT_PATH)//执行打包commandshell.exec(`npmrunbuild:${env}`,function(code,stdout,stderr){resolve(stdout)})}))},/***打开微信开发者工具*@returns{*}*/open(){returnpromiseWrap(newPromise((resolve,reject)=>{//进入项目目录shell.cd(INSTALL_PATH)//执行微信开发者工具界面“命令行启动工具”shell.exec(`cli-o${PROJECT_PATH}`,function(code,stdout,stderr){if(stderr)returnreject(stderr)resolve(stdout)})}))},/***获取微信开发者工具的端口号*@returns{Promise<*>}*/asyncgetPort(){shell.cd(PORT_PATH)//工具启动后自动开启http服务,HTTP服务的端口号记录在用户目录中。可以通过查看用户目录,查看用户目录下是否有port文件,尝试连接来查看工具是否安装/启动。const[err,data]=awaitreadFile(PORT_FILE_NAME)返回错误?errorBody(err,'读取端口号文件失败'):successBody(data,'读取端口号文件成功')},/***微信开发用户登录工具*@returns{*}*/login(){returnpromiseWrap(newPromise(async(resolve,reject)=>{//获取端口号constportData=awaitmodule.exports.getPort()if(portData.code!==0){reject(portData)return}constport=portData.dataaxios.get(`http://${HOST}:${port}/login?format=base64`).then(res=>{resolve(res.data)}).catch(e=>{reject(e)})}))},/***微信开发者工具获取预览代码*@returns{*}*/preview(){returnpromiseWrap(newPromise(async(resolve,reject)=>{constportData=awaitmodule.exports.getPort()if(portData.code!==0){reject(portData)return}constport=portData.dataaxios.get(`http://${HOST}:${port}/preview?format=base64&projectpath=${encodeURIComponent(PROJECT_PATH)}`).then(res=>{resolve(res.data)}).catch(e=>{reject(e)})})}}这里有一点需要注意,为什么只需要通过命令行调用open接口呢?那是因为http调用方法必须加上端口,比如openinterface#opentoolhttp://127.0.0.1:portnumber/open#open/refreshprojecthttp://127.0.0.1:portnumber/open?projectpath=完整项目路径如果你根本没有打开微信开发者工具,你会在以下地方找不到端口:端口号文件位置:macOS:~/Library/ApplicationSupport/WeChatwebdevelopertools/Default/.ideWindows:~/AppData/Local/WeChatwebdevelopertools/UserData/Default/.ide那么作为一个全自动编码工具,怎么可能自己手动打开微信开发者工具呢!前端后端的东西基本就这么多。最后,前端很简单,就不多说了:预览二维码