Cap1 前言
转入前端的时候,就一直做 Hybrid App 开发,所以从 React Native
到 简单的 Mui
、 Api Cloud
都尝试过,除了一些主流的开发方式,基本都有很好的调试工具,像 RN
都会有 ReactNativeDebugger
之类的工具。但由于公司需求,需要简单的 webview
网页开发的时候,RN
显然很笨重了,所以利用 Mui.js
真机框架去完成需求。最近公司有个小项目类似这样,不过 App
这一块是利用 .Net
的 Xamarin
技术构建的 App
,然后里面一些方法需要端能力才能调用数据,所以这就造成无法从浏览器调试数据。其次我利用 VueCli
生成静态页面,比编写原生的 HTML
页面高效多了,但同样无法抓取到页面动态数据的抓取。
Cap2 善用 window.alert 方法
这种方法算是调试中最傻最简单,不过在后面数据多的时候联调的时候就相对麻烦了,这里就不再描述。
Cap3 使用 Webview Debug
Webview Debug
调试方法相对而言很好了,使用过程和网页调试的控制台一模一样,基本上没什么限制,对于硬件来讲只支持 Android 4.4 (KitKat)以及以上版本
环境下,并且使用 Chrome
浏览器来支持该功能。
只需要在 Android
环境下添加下面代码即可支持:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}
如果你懒的话,也可以尝试使用 Xposed
框架支持 Webview Debug
模式:WebViewDebugHook,可以利用虚拟机尝试,毕竟虚拟机包含 root
权限。
然后打开 chrome://inspect
地址会看到调试的设备,调试方法和网页调试一样,这里就不再描述了。
参考:
但对于 Vue.js
单应用页面来说,页面包含的数据是不好抓取的,变量名混淆,页面数据压缩等等,造就页面调试进一步困难,针对于这个现象也很简单,直接将生成文件编译成和 npm run dev
环境即可:
- 修改
package.json
,新增编译任务
"build:stage": "vue-cli-service build --mode staging",
新增编辑 .env.staging
文件:
NODE_ENV = development
# just a flag
ENV = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'
VUE_CLI_BABEL_TRANSPILE_MODULES = true
这样编译后的 dist
文件在控制台可以看到文件源文件,方便变量名打断点调试。不过在调试 Vue
程序依然并不满足调试要求,因为无法调试响应式数据。
Cap4 使用 Vue.js devtools
这东西在大家眼里可能觉得只能在浏览器扩展使用,没想过能在 Webview
上使用,在 Chrome
或者 Firefox
浏览器中,里面扩展程序基本都是网页程序,只要是网页程序,相信有办法可以移植到 Webview
使用。
在 Github vue-devtools 介绍有段 Get standalone Electron app (works with any environment!)
内容吸引了我,虽说只能在 Electron
程序使用,但有办法可以在任何程序上使用,故点进去看介绍说明,就有了大概的思路。
在源码 shell-dev 使用他编译出几个 javascript
文件,注入 Vue
程序即可,现在需要解决的就是让它们能在 file://
协议中正常运行,在 shell-dev/src/devtools.js
:
import { initDevTools } from '@front'
import Bridge from '@utils/bridge'
const target = document.getElementById('target')
const targetWindow = target.contentWindow
// 1. load user app
target.src = 'target.html'
target.onload = () => {
// 2. init devtools
initDevTools({
connect (cb) {
// 3. called by devtools: inject backend
inject('./build/backend.js', () => {
// 4. send back bridge
cb(new Bridge({
listen (fn) {
targetWindow.parent.addEventListener('message', evt => fn(evt.data))
},
send (data) {
console.log('devtools -> backend', data)
targetWindow.postMessage(data, '*')
}
}))
})
},
onReload (reloadFn) {
target.onload = reloadFn
}
})
}
function inject (src, done) {
if (!src || src === 'false') {
return done()
}
const script = target.contentDocument.createElement('script')
script.src = src
script.onload = done
target.contentDocument.body.appendChild(script)
}
上述代码的 inject
方法会注入失败,查看控制台发现是 iframe
通信跨域问题,因为是 file://
导致的,所以这边修改成:
import { initDevTools } from '@front'
import Bridge from '@utils/bridge'
const target = document.getElementById('target')
const targetWindow = target.contentWindow
// 1. load user app
target.src = 'target.html'
target.onload = () => {
// 2. init devtools
initDevTools({
connect (cb) {
// 3. send back bridge
cb(new Bridge({
listen (fn) {
targetWindow.parent.addEventListener('message', evt => fn(evt.data))
},
send (data) {
console.log('devtools -> backend', data)
targetWindow.postMessage(data, '*')
}
}))
},
onReload (reloadFn) {
target.onload = reloadFn
}
})
}
直接注册 connect
方法,然后在 target.html
文件手动引入:
<script src="build/backend.js"></script>
然后打包文件在 webview
测试效果:
很显然成功了,这样很方便达到调试程序效果。
Cap5 后续
在编译 Vue-Cli
要做到自动注入上面几个所需要的文件,并且判断编译环境,例如开发环境和生产环境,一般来说生成环境不需要引入 Vue DevTools
那几个文件,由于时间仓促,这边暂时没有示例代码,所以有时间再更新博文完善下!