mpvue打小程序预览码
喂,快给我打一个小程序预览码
(点击上方公众号,可快速关注)
来源:写Bug
segmentfault.com/a/1190000015336845
需求
开发小程序的朋友们随时都会听到一句话:“喂,快给我打一个xxx环境的预览码”,无论你正在干什么,都得赶紧地回一句:“稍等,这就给你打码……”
然后苦逼的你build了一个xxx环境的包,打开了微信开发者工具,点了一下预览,等了一下,预览码出来了,你复制丢给你的爸爸们。
终于有一天,你正在专心致志做一些不可描述的事情时,“喂,快给我打一个xxx环境的预览码”,这时你内心怒吼了一句:“老子不给你打码!你自己打去!”
于是就有了这个需求,要搞个东西让爸爸们自主打码,嗯,应该就是只有一个按钮,点一下就可以出现预览二维码的东西,意淫了一下应该是这样的:
没错!就这样干!
规划一下
干大事就要从胡思乱想开始,现在来想想要搞成这个功能,需要做点什么准备工作吧。
找微信开发者工具的接口
最重要的事情莫过于看看微信开发者工具有没有给我们提供这样的接口让我们去操作,经过一番查阅文档我们会发现,果然有!
https://developers.weixin.qq.com/miniprogram/dev/devtools/http.html
会发现,文档给我们提供了两种方式的接口,命令行调用以及HTTP调用。有了接口,一切都好办了,无非就是调一下接口,拿到二维码,贴到页面上去而已嘛,很简单。
梳理开发流程
我们就把这个简单的事情,用流程图说明一下:
https://www.processon.com/view/link/5b1de951e4b06350d45ce355
所需技术
工欲善其事,必先利其器,我们要搞这个东西,还是先要把用到的技术整理一下。
微信开发者工具
一个小程序项目(这里以一个mpvue项目为例子)
前端vue + vux,这里前端没什么需要做的东西,这样的搭配纯属是因为本来就正在做移动端的东西,直接拿来用而已。
后端koa2,当然后端用什么都可以,这里选择koa2,纯属是因为我也不会用别的……
前后端HTTP请求统一用axios
涉及到node操作命令行需要用到shelljs
好像没别的东西了,用到了再说吧。
从后端开始
为了省事,直接把前后端的东西放在一起。项目目录:
可以看到server这个目录下放的都是后端的东西。
server/index.js
先看看入口文件index.js,从这里我们可以知道后端要做两件事情,第一要能访问到前端build出来的静态资源,第二要能与前端通过HTTP接口进行交互。见代码:
const path = require('path')const Koa = require('koa')const koaStatic = require('koa-static')const bodyParser = require('koa-bodyparser')const router = require('./router')const app = new Koa()const port = 9871app.use(bodyParser())// 处理静态资源 这里是前端build好之后的目录app.use(koaStatic(path.resolve(__dirname, '../dist')))// 路由处理接口app.use(router.routes()).use(router.allowedMethods())// 监听端口app.listen(9871)console.log(`[demo] start-quick is starting at port ${port}`)
静态资源方面的话使用koa-static即可,重点是怎样给前端提供接口,这就要看路由了。
server/router/index.js
const Router = require('koa-router')// 业务逻辑const wx = require('../controller/wx')const router = new Router({// 接口前缀 比如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')class WxController {/*** 根据环境对mpvue项目进行打包* @returns {Promise<void>}*/static async build (ctx) {// 前端传过来的get参数const query = ctx.request.queryif (!query || !query.env) {ctx.body = errorBody(null, '构建项目失败')return}const [err, data] = await build(query.env)ctx.body = err ? errorBody(err, '构建项目失败') : successBody(data, '构建项目成功')}/*** 打开微信开发者工具* @returns {Promise<void>}*/static async open (ctx) {const [err, data] = await open()ctx.body = err ? errorBody(err, '打开微信开发者工具失败') : successBody(data, '打开微信开发者工具成功')}/*** 登录微信开发者工具* @returns {Promise<void>}*/static async login (ctx) {const [err, data] = await login()ctx.body = err ? errorBody(err, '登录二维码返回失败') : successBody(data, '登录二维码返回成功')}/*** 查看预览码* @returns {Promise<void>}*/static async preview (ctx) {const [err, data] = await preview()ctx.body = err ? errorBody(err, '预览二维码返回失败') : successBody(data, '预览二维码返回成功')}}module.exports = WxController
为了代码更加清晰,这里将具体操作微信开发者工具的接口逻辑抽到util/wxToolApi.js里去了,仅仅处理怎样以统一格式返回给前端。
util/wxToolApi.js
const {promiseWrap, successBody, errorBody} = require('../utli')const {INSTALL_PATH, PROJECT_PATH, PORT_PATH, PORT_FILE_NAME, HOST} = require('../const')const {readFile} = require('../utli/nodeApi')const shell = require('shelljs')const axios = require('axios')module.exports = {/*** 根据环境对mpvue项目进行打包* @param env [doc, pre, prd]* @returns {*}*/build (env) {return promiseWrap(new Promise((resolve, reject) => {// 进入项目目录shell.cd(PROJECT_PATH)// 执行打包命令shell.exec(`npm run build:${env}`, function (code, stdout, stderr) {resolve(stdout)})}))},/*** 打开微信开发者工具* @returns {*}*/open () {return promiseWrap(new Promise((resolve, reject) => {// 进入项目目录shell.cd(INSTALL_PATH)// 执行微信开发者工具接口“命令行启动工具”shell.exec(`cli -o ${PROJECT_PATH}`, function (code, stdout, stderr) {if (stderr) return reject(stderr)resolve(stdout)})}))},/*** 获取微信开发者工具端口号* @returns {Promise<*>}*/async getPort () {shell.cd(PORT_PATH)// http 服务在工具启动后自动开启,HTTP 服务端口号在用户目录下记录,可通过检查用户目录、检查用户目录下是否有端口文件及尝试连接来判断工具是否安装/启动。const [err, data] = await readFile(PORT_FILE_NAME)return err ? errorBody(err, '读取端口号文件失败') : successBody(data, '读取端口号文件成功')},/*** 微信开发者工具进行登录* @returns {*}*/login () {return promiseWrap(new Promise(async (resolve, reject) => {// 获取端口号const portData = await module.exports.getPort()if (portData.code !== 0) {reject(portData)return}const port = portData.dataaxios.get(`http://${HOST}:${port}/login?format=base64`).then(res => {resolve(res.data)}).catch(e => {reject(e)})}))},/*** 微信开发者工具获取预览码* @returns {*}*/preview () {return promiseWrap(new Promise(async (resolve, reject) => {const portData = await module.exports.getPort()if (portData.code !== 0) {reject(portData)return}const port = portData.dataaxios.get(`http://${HOST}:${port}/preview?format=base64&projectpath=${encodeURIComponent(PROJECT_PATH)}`).then(res => {resolve(res.data)}).catch(e => {reject(e)})}))}}
这里有一点需要注意,为什么只有open接口需要用命令行调用方式?那是因为HTTP调用方式必须加端口,比如open接口:
# 打开工具http://127.0.0.1:端口号/open# 打开/刷新项目http://127.0.0.1:端口号/open?projectpath=项目全路径
如果你根本都没有打开微信开发者工具,在以下地方就会找不到端口:
端口号文件位置:macOS : ~/Library/Application Support/微信web开发者工具/Default/.ideWindows : ~/AppData/Local/微信web开发者工具/User Data/Default/.ide
所以作为一个全自动化打码工具,怎么可能还要自己去手动打开微信开发者工具呢!
前端
后端的东西基本就那么多,终于到前端了,前端十分简单,就不多说了:
<template><div><group title="请选择环境"><radio :options="envOption" v-model="env"></radio></group><x-button class="btn" type="default" @click.native="handlePreviewProject">点击预览</x-button><div v-if="loginImg" class="code"><divider>请先登录</divider><img class="code-img" :src="loginImg" alt=""></div><div v-if="preImg" class="code" id="preImg"><divider>预览二维码</divider><img class="code-img" :src="`${base64Prefix}${preImg}`" alt=""></div></div></template><script>import {openProject, login, previewProject, buildProject} from 'SERVICES/index'import {showLoading, hideLoading} from 'UTILS'import { Divider, XButton, Radio, Group } from 'vux'export default {data () {return {// data表示取得数据的协定名称,image/png 是数据类型名称,base64 是数据的编码方法,逗号后面就是这个image/png文件base64编码后的数据。base64Prefix: 'data:image/png;base64,',// 登录二维码loginImg: '',// 预览二维码preImg: '',// 环境 默认为docenv: 'doc',// 所有的环境选项envOption: ['doc', 'pre', 'prd']}},components: {Divider,XButton,Radio,Group},methods: {handleError (msg) {alert(msg)},async login () {const {data: {code, data, msg}} = await login()if (code !== 0) {this.handleError(msg)return code}this.loginImg = datareturn code},async previewProject () {const {data: {code, data, msg}} = await previewProject()if (code !== 0) {this.handleError(msg)return code}this.preImg = datareturn code},async handlePreviewProject () {showLoading()// 重置二维码this.resetImg()// 打开微信开发者工具const {data: {code}} = await openProject()if (code !== 0) {// 登录微信开发者工具await this.login()hideLoading()return}// 根据环境打包await buildProject(this.env)// 预览await this.previewProject()hideLoading()},resetImg () {this.loginImg = ''this.preImg = ''}}}</script><style lang='less'>.btn {width: 90%!important;margin: 30px auto 30px auto;}.code {display: flex;align-items: center;flex-direction: column;.code-img {width: 300px;height: 300px;}}</style>
这里有一个坑就是,login返回的base64是带了 data:image/jpeg;base64,前缀的,所以可以直接放到img的src里,但是获取预览码的preview返回的却没有这个前缀!所以需要自己加上去,就是那个 base64Prefix:'data:image/png;base64,'
最后
其实到这里已经基本实现了整个打码功能,但如果真的要可以用还有很多事情没做。
部署到测试机器上。虽然可以直接用自己的机子作为部署这个工具的机器,但这实在是有点……如果要部署到测试机器上,有一个问题就是,微信开发者工具依赖图形界面,而服务器一般是命令行,虽然有 https://github.com/cytle/wechatwebdevtools 这样的项目移植微信开发者工具到linux,但这种部署方式似乎还是怪怪的。
假设完成了上述部署,进行小程序项目打包的环节需要修改一下,变成根据选择的环境,到相应的代码仓库(比如gitlab)拉取该环境的最新代码,然后进行安装依赖才能执行打包命令。
既然都做到这一步了,也不差把上传小程序也加上去,微信开发者工具接口也有提供,这样一来整个测试打码到上线的步骤都有了。
End~
【关于投稿】
如果大家有原创好文投稿,请直接给公号发送留言。
① 留言格式:
【投稿】+《 文章标题》+ 文章链接
② 示例:
【投稿】《不要自称是程序员,我十多年的 IT 职场总结》:http://blog.jobbole.com/94148/
③ 最后请附上您的个人简介哈~
觉得本文对你有帮助?请分享给更多人
关注「前端大全」,提升前端技能
mpvue打小程序预览码的更多相关文章
- 微信小程序--预览previewImage(长按保存图片)
最近开发小程序,想实现二维码图片长按保存,发现无法保存,只能让图片先预览,再保存.注意:只有太阳码才有长按保存和识别功能,普通二维码只有长按保存功能. <image class='banner' ...
- 小程序预览pdf文件
有个业务需求,需要在小程序查看客户已开的发票 发票地址: https://www.chinaeinv.com/p.jspa?cxxxxxxxxxxxx 刚开始是想利用webview当作外链进行跳转访问 ...
- 微信小程序预览图片
选择图片时可设置图片是否是原图,图片来源.这用的也挺常见的,比如个人中心中设置头像,可以与wx.upLoadFile()API使用 主要方法: wx.chooseImage(object) wxml ...
- 小程序预览图片wx.previewImage
效果图: ====> ==> 代码: <image mode='aspectFill' bindtap='previewImage' data-src='{{dataList ...
- 微信小程序预览Word文档
<view data-url="https://xxxcom/attachment/word.docx" data-type="docx" catchta ...
- 近期热门微信小程序demo源码下载汇总
近期微信小程序demo源码下载汇总,乃小程序学习分析必备素材!点击标题即可下载: 即速应用首发!原创!电商商场Demo 优质微信小程序推荐 -秀人美女图 图片下载.滑动翻页 微信小程序 - 新词 GE ...
- 为什么选择MpVue进行小程序的开发
前言 mpvue是一款使用Vue.js开发微信小程序的前端框架.使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为H5和小程序提供了代码复用的能力.如果想将 H5 项目改造为小程序,或开发 ...
- 微信小程序二维码推广统计
微信小程序可以通过生成带参数的二维码,那么这个参数是可以通过APP的页面进行监控的 这样就可以统计每个二维码的推广效果. 今天由好推二维码推出的小程序统计工具HotApp小程序统计也推出了带参数二维码 ...
- 小程序二维码生成接口API
获取小程序码 我们推荐生成并使用小程序码,它具有更好的辨识度.目前有两个接口可以生成小程序码,开发者可以根据自己的需要选择合适的接口. 接口A: 适用于需要的码数量较少的业务场景 接口地址: http ...
随机推荐
- 【DSP开发】帮您快速入门 TI 的 Codec Engine
德州仪器半导体技术(上海)有限公司 通用DSP 技术应用工程师 崔晶 德州仪器(TI)的第一颗达芬奇(DaVinci)芯片(处理器)DM6446已经问世快三年了.继DM644x之后,TI又陆续推出了D ...
- [转载]由浅入深探究mysql索引结构原理、性能分析与优化
第一部分:基础知识第二部分:MYISAM和INNODB索引结构1. 简单介绍B-tree B+ tree树 2. MyisAM索引结构 3. Annode索引结构 4. MyisAM索引与InnoDB ...
- css设置滚动条并显示或隐藏
看效果,没有滚动条,超出div,开发中肯定不行. 有滚动条 最后就是想隐藏滚动条 代码 有滚动条并显示 <!DOCTYPE html> <html lang="en&quo ...
- 【转】转载一篇优质的讲解epoll模型的文章
从事服务端开发,少不了要接触网络编程.Epoll 作为 Linux 下高性能网络服务器的必备技术至关重要,Nginx.Redis.Skynet 和大部分游戏服务器都使用到这一多路复用技术. Epoll ...
- 学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧
目录 学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧 25.1 Shell中的色彩处理 25.2 awk基本应用 25.2.1 概念 25.2.2实例演示 25.3 awk ...
- HTML5 & CSS初学者教程(详细、通俗易懂)
前端语言基础:HTML5 & CSS (一) HTML5:超文本标记语言 (1) 基本概念 是由一系列成对出现的元素标签(标记)嵌套组合而成 ( XML也是标签构成的 ) 这些标签以的形式出现 ...
- 【转】mysql分库分表,数据库分库分表思路
原文:https://www.cnblogs.com/butterfly100/p/9034281.html 同类参考:[转]数据库的分库分表基本思想 数据库分库分表思路 一. 数据切分 关系型数 ...
- HADR和TSA需要注意的问题
1.必须将主备数据库都执行一次完全备份,然后使用主库执行online备份后同步至备库: 2.同一台服务器只能添加一个TSA集群管理器,此服务器中无论有几个实例和几个数据库,都会被添加至首次创建的集群中 ...
- HTTP用户认证、追加协议以及相关技术简单学习
1. 用户身份认证 BASIC认证(基本认证): DIGEST(摘要认证): SSL客户端认证: FormBase认证(表单认证)常用: session和cookie 2. 基于HTTP的追加协议 A ...
- SHA1签名工具类java
package com.net.util; import java.security.MessageDigest; import java.util.Iterator; import java.uti ...