上次web沙龙上和大家分享了关于移动时代汹涌而来的一些具体数据,同时无论是基于browser还是WebView,我们团队都了一些实践。本文旨在对目前的移动终端上web前端调试遇到的问题和解决方案进行初步探讨,从而抛砖引玉,引起大家的进一步关注、分析和思考(如同之前对web性能测试解决方案的一系列讨论)
首先,我们来看下在PC上调试的一些常用的手段和技巧。
序号 | 功能 | 工具 |
1 | 测试环境配置 | Hosts, fiddler等及我们团队的利器NoHost |
2 | DOM节点,样式校正,Console | 浏览器自带工具及第三方对比工具 |
3 | 网络抓包 | 浏览器自带工具或httpwatch、fiddler第三方工具 |
4 | 文件替换 | fiddler、minnow等代理工具 |
5 | 脚本调试 | 浏览器自带,Script debugger,VS等 |
6 | 性能检查 | 浏览器自带或dynatrace等第三方工具 |
然而当我们把页面放到移动终端的时候,会猛然发现在PC上的技能和工具顿时没有了用武之地。在操作系统、屏幕大小、浏览器自身能力和扩展能力以及优秀的第三方工具等等各个方面都受到了很大的限制。所以,抛弃过往的工具,我们只能另辟蹊径。同时也期待移动设备上的浏览器自身会有很好的内置调试器出现,虽然用在webview上还要很多额外工作,但是至少我们在PC内嵌上做了很多尝试:)。
一、PC上的开发和调试方式,是否还有用?
当然还是有效的,因为我们70%以上的开发工作仍然是在PC上进行的。你仍然可以使用你最爱的firefox/firebug或chrome进行开发和基础调试。同时,所幸的是各个移动版本的浏览器(无论是内置,还是第三方浏览器)都对HTML5 basic 和CSS3 basic都有较好的支持(如下图)。所以在不使用特殊特性的情况下,基于PC标准浏览器的自我开发和调试是有效。而不同终端的差异或非统一标准化的那部分,我们后面再看如何解决。
二、采用模拟器或云工具进一步进行测试
通过User-Agent的处理模拟终端请求等方式并不能真的让我们的逻辑跑在预期的平台上,所以终端开发同学大都会使用模拟器这个东西。模拟器是手机操作系统开发商提供给开发者高仿真机运行的工具,开发者可以在模拟器窗口上模拟手机操作系统载入和按键触屏操作等。用模拟器的好处在于可以复用PC上的一些网络配置和抓包工具(但有些设备是不支持USB共享网络的),这里不赘述(如下图)。
对于已经发布到外网的页面,我们不但可以模拟器,还可以使用云服务。没错,现在是云时代了,无论什么都可以云端化,而且云背后有些是挂载的真机哦(eg:WebPageTest就是挂载真正的浏览器来进行性能测试的)。这里我们简单介绍两个口碑较好的工具:
1、DeviceAnywhere.com
2、Perfectomobile.com
其基本原理是把实际手持设备连接到它的数据中心,然后通过一个单独的应用程序为最终用户创建虚拟视图。这个数据中心就像是 “Matrix” 的一部分,可以通过 Internet 连接访问它,最终得到 “Borg” 的线索。
同时,目前也了解到其他团队的一些研发测试情况是抓主流的设备进行测试,并不是考虑大而全的问题,这个思路作为参考补充。
三、测试环境和内网研发问题如何处理?
对于有些安全级别比较高的公司,是不允许建立热点的,同时开发运营测试网络和办公网络或手机可以接入的网络是隔离的。这种情况对于没有发布和多个测试环境场景的移动web应用来收,就非常的被动了。除了找公司网管协商对策和发布未在真机跑过测试的代码出去之外,我们有更简单的技术解决方案—NoHost(即通过外网代理层+IP帐号等权限控制+Local DNS,来实现多测试环境轻松访问和切换)。
接入NoHost系统之后,这个问题便迎刃而解。开发这需要做的事情就是在页面上浮出选择框上选择你要使用的环境即可。同时还有个最大的好处:可以在replay系统上如同fiddler一样完全重现终端设备上的访问情况。
这里我们还有一些工作需要做:
1、NoHost环境切换按钮在移动终端展示的UI优化
2、NoHost环境切换按钮的隐藏逻辑支持
3、移动终端案例,支持到NoHost官网
四、如何在真机上进行远程调试处理?
首先很多同学肯定会先想到,是不是可以直接使用浏览器的remote debugging模式呢?这里主要考虑到以下几个原因:
1、不是所有设备和操作系统都支持通过USB进行远程调试
2、不同浏览器的远程调试方法不同,且支持程度不一致,导致远程调试相对复杂
3、不支持WebView(这条就足够使得我们放弃)
各厂商的remote debugging支持情况如下表概述:(部分数据不全)
序号 | 浏览器 | 说明 | 功能支持 | 基本原理 |
1 | Opera | 最早支持remote debugging | 断点 |
HTML|CSS处理
Console等1、内置调试功能
2、桌面建立server
3、基于Scope传输协议进行通信(json结构)2Chrome/webkit1、Andorid 4.0+才支持,iOS6.0将支持,blackberry TabletOS支持
2、通过chrome的remote-debugging-port参数启动断点
HTML|CSS处理
Console等1、内置调试功能
2、chrome启动socket server
3、json格式通信3Firefox1、通过firebug插件Crossfire处理
2、FF15后支持新特性断点
Console等
新协议可以通过互联网进行数据通信4IE1、Crossfile for ie
2、Gotcha断点
Console等文档较少
虽然不能直接使用浏览器的remote debugging模式,但是浏览器在这方面做的努力却是我们可以学习和参考的。即可以通过通用的调试模式来进行处理:
1、移动终端浏览器(或页面)内置调试功能
2、建立Server,为终端和PC调试端提供数据通讯协议
3、PC调试端进行前端展示和命令输出
基本流程如下图:
通过这个调试模式能做什么,完全取决于JavaScript和Server的能力。即JavaScript和Server能做什么,我们就可以通过桌面远程调试终端页面的什么。从下图各自的能力来看,实现我们主流的功能是完全不是问题,只要将JavaScript的能力通过Server来透传即可。
功能 | JavaScript | Server |
断点 | No | No |
HTML|CSS在线处理 | Yes | No |
Console等 | Yes | No |
文件读取 | No | Yes |
在PC调试端的前端表现这里可以复用已有的UI和模式,FirebugLite和Chrome的Inspector都是很不错的选择。这里可以直接复用Weinre这个工具的实现(这个工具目前在业内已经有较大范围使用,朋友网yuni目前也是用的这个工具)。
Weinre的相关说明:http://blog.csdn.net/dojotoolkit/article/details/6280924
,我也转过yuni的邮件给大家,这里就不赘述了,效果很不错,强力推荐大家使用下,然后整合到我们的研发流程和NoHost里。
但是,还有一个很重要的问题,根据上面JavaScript和Server能力的分布,我们发现断点调试还没实现!
这个无法实现么?
五、远程调试如何实现JavaScript断点(breakpoint)调试?
经过分析和学习,发现这个功能已经有牛人(Aleksander Kmetec)实现了,这里就直接给出他的实现原理和方法。
原理:
将请求的所有外链JavaScript进行重写,使其结合移动端JavaScript可以实现按行执行。
举例:
1、浏览器第一个加载调试控制的JS(这里是:https://github.com/lexandera/Aardwolf/blob/master/js/aardwolf.js)
2、后续请求的所有外链JS都会被按照一定的规则重写,eg:
1 |
2 var $number1;
3 var $number2;
…
7 $(function() {
8 /* Locate number input fields */
9 $number1 = $(‘#number1’);
10 $number2 = $(‘#number2’);
11 $number3 = $(‘#number3’);
12 $result = $(‘#result’);
13
14 $(‘#calculate’).click(calculate);
15 $(‘#reset’).click(reset);
16 });
…var __this = this;try { Aardwolf.pushStack(“<toplevel>”, “/calc.js”, ‘0’); var aardwolfEvalFunc = function(aardwolfEval) { return eval(aardwolfEval); };
Aardwolf.updatePosition(“/calc.js”, 2, false, aardwolfEvalFunc);var $number1;
Aardwolf.updatePosition(“/calc.js”, 3, false, aardwolfEvalFunc);var $number2;
Aardwolf.updatePosition(“/calc.js”, 7, false, aardwolfEvalFunc);$(function() {var __this = this;try { Aardwolf.pushStack(“<anonymous>”, “/calc.js”, ‘7’); var aardwolfEvalFunc = function(aardwolfEval) { return eval(aardwolfEval); };
/* Locate number input fields */
Aardwolf.updatePosition(“/calc.js”, 9, false, aardwolfEvalFunc);$number1 = $(‘#number1’);
Aardwolf.updatePosition(“/calc.js”, 10, false, aardwolfEvalFunc);$number2 = $(‘#number2’);
Aardwolf.updatePosition(“/calc.js”, 11, false, aardwolfEvalFunc);$number3 = $(‘#number3’);
Aardwolf.updatePosition(“/calc.js”, 12, false, aardwolfEvalFunc);$result = $(‘#result’);
Aardwolf.updatePosition(“/calc.js”, 14, false, aardwolfEvalFunc);$(‘#calculate’).click(calculate);
Aardwolf.updatePosition(“/calc.js”, 15, false, aardwolfEvalFunc);$(‘#reset’).click(reset);
} catch (aardwolfEx) { if (!aardwolfEx.rethrown) { Aardwolf.reportException(aardwolfEx); } aardwolfEx.rethrown = true; throw aardwolfEx;} finally { Aardwolf.popStack();}});
3、执行每行代码的时候,Aardwolf都会判断目前是否是被设置成了断点,是否有代码需要执行。
4、最核心的是Aardwolf.updatePosition函数,记录了文件名,原始行号,是否设置debugger,闭包等基本信息,为后续做断点和调试做准备。
5、通过上一节提到的Server中转的方式,在收到新的断点和console的时候,Aardwolf.updatePosition可以第一时间介入,且不需要重新拉取任何文件。
OK,基于纯JavaScript和纯Server的都不能实现断点调试,而把两者结合就刚刚好可以完成,想法很棒。原理搞清楚了,那么对我们来说也就没什么困难的了,复用Aardwolf的逻辑整合到我们的NoHost系统即可。
六、NoHost对移动终端调试的意义和方法探讨
序号 | 功能 | 工具 |
1 | 测试环境配置 | NoHost |
2 | DOM节点,样式校正,Console | NoHost+类weinre |
3 | 网络抓包 | NoHost+Replay |
4 | 文件替换 | NoHost+多套环境 |
或NoHost+配置系统5脚本调试NoHost+类Aardwolf6性能检查NoHost+phantomJS+YSlow
NoHost和NodeJS时代来临了,不是么?
参考内容:
1、HTML5终端支持情况:http://mobilehtml5.org/
2、手机浏览器HTML5支持情况调查:http://www.williamlong.info/archives/3075.html
3、用 DeviceAnywhere 远程测试移动设备:http://www.infoq.com/cn/vendorcontent/show.action?vcr=998
4、Web移动应用调试工具——Weinre:http://blog.csdn.net/dojotoolkit/article/details/6280924
5、WebKit Remote Debugging:https://www.webkit.org/blog/1620/webkit-remote-debugging/
6、weinre – Running:http://people.apache.org/~pmuellr/weinre/docs/latest/Running.html
7、Remote Debugging in Firefox Mobile:http://lucasr.org/2012/03/28/remote-debugging-in-firefox-mobile/
8、aardwolf介绍:http://lexandera.com/aardwolf/
9、aardwolf在Github:https://github.com/lexandera/Aardwolf