热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mpvue打小程序预览码

喂,快给我打

喂,快给我打一个小程序预览码

昨天

(点击上方公众号,可快速关注)

 

来源:写Bug

segmentfault.com/a/1190000015336845

 

需求

开发小程序的朋友们随时都会听到一句话:“喂,快给我打一个xxx环境的预览码”,无论你正在干什么,都得赶紧地回一句:“稍等,这就给你打码……”

然后苦逼的你build了一个xxx环境的包,打开了微信开发者工具,点了一下预览,等了一下,预览码出来了,你复制丢给你的爸爸们。

终于有一天,你正在专心致志做一些不可描述的事情时,“喂,快给我打一个xxx环境的预览码”,这时你内心怒吼了一句:“老子不给你打码!你自己打去!”

于是就有了这个需求,要搞个东西让爸爸们自主打码,嗯,应该就是只有一个按钮,点一下就可以出现预览二维码的东西,意淫了一下应该是这样的:

mpvue打小程序预览码

没错!就这样干!

规划一下

干大事就要从胡思乱想开始,现在来想想要搞成这个功能,需要做点什么准备工作吧。

找微信开发者工具的接口

最重要的事情莫过于看看微信开发者工具有没有给我们提供这样的接口让我们去操作,经过一番查阅文档我们会发现,果然有!

https://developers.weixin.qq.com/miniprogram/dev/devtools/http.html

会发现,文档给我们提供了两种方式的接口,命令行调用以及HTTP调用。有了接口,一切都好办了,无非就是调一下接口,拿到二维码,贴到页面上去而已嘛,很简单。

梳理开发流程

我们就把这个简单的事情,用流程图说明一下:

https://www.processon.com/view/link/5b1de951e4b06350d45ce355

mpvue打小程序预览码

所需技术

工欲善其事,必先利其器,我们要搞这个东西,还是先要把用到的技术整理一下。

  1. 微信开发者工具

  2. 一个小程序项目(这里以一个mpvue项目为例子)

  3. 前端vue + vux,这里前端没什么需要做的东西,这样的搭配纯属是因为本来就正在做移动端的东西,直接拿来用而已。

  4. 后端koa2,当然后端用什么都可以,这里选择koa2,纯属是因为我也不会用别的……

  5. 前后端HTTP请求统一用axios

  6. 涉及到node操作命令行需要用到shelljs

好像没别的东西了,用到了再说吧。

从后端开始

为了省事,直接把前后端的东西放在一起。项目目录:

mpvue打小程序预览码

可以看到server这个目录下放的都是后端的东西。

server/index.js

先看看入口文件index.js,从这里我们可以知道后端要做两件事情,第一要能访问到前端build出来的静态资源,第二要能与前端通过HTTP接口进行交互。见代码:

  1. const path = require('path')

  2. const Koa = require('koa')

  3. const koaStatic = require('koa-static')

  4. const bodyParser = require('koa-bodyparser')

  5. const router = require('./router')

  6. const app = new Koa()

  7. const port = 9871

  8. app.use(bodyParser())

  9. // 处理静态资源 这里是前端build好之后的目录

  10. app.use(koaStatic(

  11.  path.resolve(__dirname, '../dist')

  12. ))

  13. // 路由处理接口

  14. app.use(router.routes()).use(router.allowedMethods())

  15. // 监听端口

  16. app.listen(9871)

  17. console.log(`[demo] start-quick is starting at port ${port}`)

静态资源方面的话使用koa-static即可,重点是怎样给前端提供接口,这就要看路由了。

server/router/index.js

  1. const Router = require('koa-router')

  2. // 业务逻辑

  3. const wx = require('../controller/wx')

  4. const router = new Router({

  5.  // 接口前缀 比如open接口 请求路径就是/api/open

  6.  prefix: '/api'

  7. })

  8. router.get('/open', wx.open)

  9.  .get('/login', wx.login)

  10.  .get('/preview', wx.preview)

  11.  .get('/build', wx.build)

  12. module.exports = router

这里可以清晰看到,后端提供了四个接口,但具体每个接口的业务逻辑则封装在controller里的wx.js,如果以后还有别的业务逻辑,就在controller加相应的模块即可。

server/controller/wx.js

  1. // 微信开发者工具接口调用逻辑

  2. const {open, login, preview, build} = require('../utli/wxToolApi')

  3. // 处理成功失败返回格式的工具

  4. const {successBody, errorBody} = require('../utli')

  5. class WxController {

  6.  /**

  7.   * 根据环境对mpvue项目进行打包

  8.   * @returns {Promise}

  9.   */

  10.  static async build (ctx) {

  11.    // 前端传过来的get参数

  12.    const query = ctx.request.query

  13.    if (!query || !query.env) {

  14.      ctx.body = errorBody(null, '构建项目失败')

  15.      return

  16.    }

  17.    const [err, data] = await build(query.env)

  18.    ctx.body = err ? errorBody(err, '构建项目失败') : successBody(data, '构建项目成功')

  19.  }

  20.  /**

  21.   * 打开微信开发者工具

  22.   * @returns {Promise}

  23.   */

  24.  static async open (ctx) {

  25.    const [err, data] = await open()

  26.    ctx.body = err ? errorBody(err, '打开微信开发者工具失败') : successBody(data, '打开微信开发者工具成功')

  27.  }

  28.  /**

  29.   * 登录微信开发者工具

  30.   * @returns {Promise}

  31.   */

  32.  static async login (ctx) {

  33.    const [err, data] = await login()

  34.    ctx.body = err ? errorBody(err, '登录二维码返回失败') : successBody(data, '登录二维码返回成功')

  35.  }

  36.  /**

  37.   * 查看预览码

  38.   * @returns {Promise}

  39.   */

  40.  static async preview (ctx) {

  41.    const [err, data] = await preview()

  42.    ctx.body = err ? errorBody(err, '预览二维码返回失败') : successBody(data, '预览二维码返回成功')

  43.  }

  44. }

  45. module.exports = WxController

为了代码更加清晰,这里将具体操作微信开发者工具的接口逻辑抽到util/wxToolApi.js里去了,仅仅处理怎样以统一格式返回给前端。

util/wxToolApi.js

  1. const {promiseWrap, successBody, errorBody} = require('../utli')

  2. const {INSTALL_PATH, PROJECT_PATH, PORT_PATH, PORT_FILE_NAME, HOST} = require('../const')

  3. const {readFile} = require('../utli/nodeApi')

  4. const shell = require('shelljs')

  5. const axios = require('axios')

  6. module.exports = {

  7.  /**

  8.   * 根据环境对mpvue项目进行打包

  9.   * @param env [doc, pre, prd]

  10.   * @returns {*}

  11.   */

  12.  build (env) {

  13.    return promiseWrap(new Promise((resolve, reject) => {

  14.      // 进入项目目录

  15.      shell.cd(PROJECT_PATH)

  16.      // 执行打包命令

  17.      shell.exec(`npm run build:${env}`, function (code, stdout, stderr) {

  18.        resolve(stdout)

  19.      })

  20.    }))

  21.  },

  22.  /**

  23.   * 打开微信开发者工具

  24.   * @returns {*}

  25.   */

  26.  open () {

  27.    return promiseWrap(new Promise((resolve, reject) => {

  28.      // 进入项目目录

  29.      shell.cd(INSTALL_PATH)

  30.      // 执行微信开发者工具接口“命令行启动工具”

  31.      shell.exec(`cli -o ${PROJECT_PATH}`, function (code, stdout, stderr) {

  32.        if (stderr) return reject(stderr)

  33.        resolve(stdout)

  34.      })

  35.    }))

  36.  },

  37.  /**

  38.   * 获取微信开发者工具端口号

  39.   * @returns {Promise<*>}

  40.   */

  41.  async getPort () {

  42.    shell.cd(PORT_PATH)

  43.    // http 服务在工具启动后自动开启,HTTP 服务端口号在用户目录下记录,可通过检查用户目录、检查用户目录下是否有端口文件及尝试连接来判断工具是否安装/启动。

  44.    const [err, data] = await readFile(PORT_FILE_NAME)

  45.    return err ? errorBody(err, '读取端口号文件失败') : successBody(data, '读取端口号文件成功')

  46.  },

  47.  /**

  48.   * 微信开发者工具进行登录

  49.   * @returns {*}

  50.   */

  51.  login () {

  52.    return promiseWrap(new Promise(async (resolve, reject) => {

  53.      // 获取端口号

  54.      const portData = await module.exports.getPort()

  55.      if (portData.code !== 0) {

  56.        reject(portData)

  57.        return

  58.      }

  59.      const port = portData.data

  60.      axios.get(`http://${HOST}:${port}/login?format=base64`)

  61.        .then(res => {

  62.          resolve(res.data)

  63.        })

  64.        .catch(e => {

  65.          reject(e)

  66.        })

  67.    }))

  68.  },

  69.  /**

  70.   * 微信开发者工具获取预览码

  71.   * @returns {*}

  72.   */

  73.  preview () {

  74.    return promiseWrap(new Promise(async (resolve, reject) => {

  75.      const portData = await module.exports.getPort()

  76.      if (portData.code !== 0) {

  77.        reject(portData)

  78.        return

  79.      }

  80.      const port = portData.data

  81.      axios.get(`http://${HOST}:${port}/preview?format=base64&projectpath=${encodeURIComponent(PROJECT_PATH)}`)

  82.        .then(res => {

  83.          resolve(res.data)

  84.        })

  85.        .catch(e => {

  86.          reject(e)

  87.        })

  88.    }))

  89.  }

  90. }

这里有一点需要注意,为什么只有open接口需要用命令行调用方式?那是因为HTTP调用方式必须加端口,比如open接口:

  1. # 打开工具

  2. http://127.0.0.1:端口号/open

  3. # 打开/刷新项目

  4. http://127.0.0.1:端口号/open?projectpath=项目全路径

如果你根本都没有打开微信开发者工具,在以下地方就会找不到端口:

  1. 端口号文件位置:

  2.  

  3. macOS : ~/Library/Application Support/微信web开发者工具/Default/.ide

  4.  

  5. Windows : ~/AppData/Local/微信web开发者工具/User Data/Default/.ide

所以作为一个全自动化打码工具,怎么可能还要自己去手动打开微信开发者工具呢!

前端

后端的东西基本就那么多,终于到前端了,前端十分简单,就不多说了:

  1.  

  2.  

这里有一个坑就是,login返回的base64是带了 data:image/jpeg;base64,前缀的,所以可以直接放到img的src里,但是获取预览码的preview返回的却没有这个前缀!所以需要自己加上去,就是那个 base64Prefix:'data:image/png;base64,'

最后

其实到这里已经基本实现了整个打码功能,但如果真的要可以用还有很多事情没做。

  1. 部署到测试机器上。虽然可以直接用自己的机子作为部署这个工具的机器,但这实在是有点……如果要部署到测试机器上,有一个问题就是,微信开发者工具依赖图形界面,而服务器一般是命令行,虽然有 https://github.com/cytle/wechatwebdevtools 这样的项目移植微信开发者工具到linux,但这种部署方式似乎还是怪怪的。

  2. 假设完成了上述部署,进行小程序项目打包的环节需要修改一下,变成根据选择的环境,到相应的代码仓库(比如gitlab)拉取该环境的最新代码,然后进行安装依赖才能执行打包命令。

  3. 既然都做到这一步了,也不差把上传小程序也加上去,微信开发者工具接口也有提供,这样一来整个测试打码到上线的步骤都有了。

End~

 

 

【关于投稿】

 

如果大家有原创好文投稿,请直接给公号发送留言。

 

① 留言格式:
【投稿】+《 文章标题》+ 文章链接

② 示例:
【投稿】《不要自称是程序员,我十多年的 IT 职场总结》:http://blog.jobbole.com/94148/

③ 最后请附上您的个人简介哈~

 

 

 

觉得本文对你有帮助?请分享给更多人

关注「前端大全」,提升前端技能

mpvue打小程序预览码

mpvue打小程序预览码

阅读原文
转载自:https://mp.weixin.qq.com/s/idSSZR8bfENOeKFjPJxIsg

推荐阅读
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
author-avatar
q40796672
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有