当今移动设备这边厢风景已由WebKit独领风骚,所以,为移动设备上Web前端开发提供支持的各种工具以及基础设施都来自WebKit的Inspector。因此,我将着重讲述一下WebKit的Inspector,深入阐述它所具有的全部特性集,并说说应该在什么情况下以及如何使用WebKit的Inspector。 Google以及Chrome团队已经给出了大量关于Inspector的资料。正是由于这方面的发展变化,才使得整个一大类新的比较复杂而炫目的应用程序能够克服自身巨大的复杂性而成为现实。这当然是个好消息,但随着我不断地同越来越多的Web开发人员交谈,我逐渐发现,他们中有很多人在开发过程以及工具使用方面,并没有及时跟进这些变化,或者说,他们并没有充分利用现有的工具。为了弥补该问题,我这篇博文不仅会带领你领略Inspector的所有特性,而且还会重点介绍一些查找bug的技术以及一些我认为不可或缺的特性开发技术。写本博文就是为了要它即可看又可分享。你可以点击本文中的任何一个小标题,将指向特定技巧/技术或特性的URL分享给你的朋友们(译者注:由于翻译排版的问题,这个功能就木有了)。 写在前面 在我们开始深入探讨之前,要声明一点就是我并不认为我在开发过程以及工具使用方面的知识是绝对正确的。如果你发现其中观点有误、信息过时或者用处不大,请给我发封email告诉我你的观点,我将洗耳恭听。 如果你刚结识inspector,或者对它了解并不多,那就劳驾您边读本文边摆弄摆弄它。亲身试验是最好的学习方法!“但是宝贝啊,我可不想为了试验这些东西而不断地建一堆新文件然后载入并编辑它们!我还要喂孩子呢!”。 我听到你这么说了,而且我也赞同你的这个观点,这也正是为什么会有“data:URLScheme”的原因! 请试验一下: 在Chrome中打开一个新标签(tab),把下列内容粘贴到地址栏并敲击回车键: data:text/html,<b>ZOMG I AM BOLD!?!!?</b> 这是在页面中弄一些HTML并查看其展示情况、试验一些新想法最简便的方法。冒号后面的所有内容都会被浏览器看作是HTML,一旦装载完成后,就可以打开Inspector进行各种试验了。
一个Inspector就够了 WebKit上现在可不止有一个Inspector。实际上任何时候你都可以使用以下所列浏览器里提供的5个Inspector:
我是按照从最旧到最新的顺序对它们进行排列的。Chrome Canary总能得到最新特性方面的更新。在最早尝鲜的人用过一段时间之后,这些新特性会逐渐并入Chromium、WebKit Nightlies以及Chrome,最后并入的是Safari。在任何时候,Safari的Inspector都落后于Chrome Canary大约一年的开发时间。也就是说,请你使用Chrome Canary进行开发吧。 设置好环境 棒极了。你已经下载并打开了Chrome Canary,启动了你的网站之后,你摩拳擦掌并挽起了袖子。 请敲击按键CMD+J打开Inspector,也可以用鼠标右键点击某一个的元素并单击“Inspect Element”菜单。 现在来设置一个舒服的环境。要做的第一件事是先熟悉一下UI。花点时间点击一下你所看到的每一个按钮,还可以在按钮上悬停一下鼠标,查看按钮的提示信息(tooltip),看看到底它们能干些什么事情。 停靠到右侧你要做的第一件事是,点击界面底端右侧的齿轮图标,调出Inspector的设置界面。先别管设置界面那极其丑陋的平视显式格式(HUD display), 我强烈推荐选择“Dock to Right”这个选项(译者注:其实可以把Inspector拖到右侧停靠)。选择该选项后,Inspector就会停靠在窗口右侧。你要是将Inspector弹出为独立窗口,再同时打开多个Inspector,情况就会很混乱。如果停靠在底部,那么水平方向的许多空间得不到利用,反而垂直方向上能看到的内容太有限了。停靠到右侧能在双方面达到最好的效果。你所看到的应该是如下图所示的情况: ![]() 仿真触屏事件如果你正在开发的是移动应用,那么这个设置(在设置界面里)就很有必要选择了。
快捷键还有一个小技巧可以帮你提高使用Inspector的效率,就是熟练使用键盘快捷键。 切换到Elements面板(有些其它面板会吞掉键盘敲击事件),然后键入“?”。 随后就会出现极其丑陋的平视显式格式的界面,其中列出了一个快捷键列表。最有用的快捷键是切换到Script面板的那个,随后我们再细说这些。 ![]()
检视iFrame一直以来,iFrames的调试都是摆在Web开发人员面前的一个难题。现在再也不是了!你现在可以指定想让Inspector检视哪个iFrame,指定的方法是通过下图所示的inspector底端中间部分的弹出式选择框进行。这个选择框有些稀奇,只有你对控制台进行扩展(在Elements面板下按Esc键)之后才能显示出来。 ![]()
控制台 甜心大宝贝,你环境都弄好了, 音乐也响起了,此时心必向往之。现在你需要真的做些事情了:运行命令,检查某个函数的输出结果,看看某个方法是否存在,或者看看有什么日志/错误/警告。这些都是控制台可以帮助你干的事情。 控制台可是个到处惹是生非的坏家伙,实际上它不仅仅有自己的面板,而且在任何面板中都可以通过点击界面底部左侧的“>=”图标或者按Esc键把它调出来使用。 它正好也是比较直观的功能之一: 键入一些表达式并敲回车键,然后就能看到相应的输出结果。日志按发生时间顺序显示,点击右侧的文件名就可以到达Scripts面板。但你可能还不知道,在控制台面板中使用“shift + enter”,你可以键入多行表达式。这对编写包含匿名函数或复杂语句的比较长的命令十分有帮助。你还可以在日志多得看不过来的情况下,键入“ctrl + L”清除控制台中显示的内容。 从DOM调试的角度看,控制台里比较酷的一个功能是它可同Elements面板(这个我们在下一节中进行讨论)进行集成。在Elements面板选中的元素可以便捷地通过使用 “$0”进行访问。它代表对选中元素的引用,你可以对该元素进行一些交互操作。另一方面,只要你在控制台中看到有打印出来的DOM节点,你都可以右击该节点并点击“Reveal in Elements Panel”菜单就可以在DOM中快速找到该节点了。 ![]()
Elements面板 你设置好了环境并准备好开始创建你的应用程序了。第一步是要让你的HTML和CSS表现正常(或者还有JavaScript,这取决于你的工作流程)。此时就是该Elements面板上场大显身手的时候了。 DOM操作Elements面板在你需要修改/调试CSS或者DOM时就该派上用场了。Elements面板的主要区域里实时地显示着你的DOM的层次结构。随着你用JavaScript对它们进行修改,你就能在Elements面板中实时的看到修改的结果。箭头键可以用来在层次结构中上下游走,而且你还可以双击任意属性对其名或其值进行编辑。你还可以在DOM中点击后拖拽任意节点重新排列节点顺序并改变它们的位置。 因为Elements面板反映的是实时信息,所以我发现我自己经常会在这个面板进行大量的试验。将这个节点拖拽到这里,看看是不是修复了z坐标方向的显示顺序问题(z-index ordering issue)? 那个DIV没有显示出来,看看它是不是被另外一层给遮挡住了? 在inspector的底部,你能看到有个放大镜。你点击它之后,就可以将其悬停在你的应用之上,放大镜就会高亮显示你选择的节点。这一招在你需要快速选择一个嵌套层次非常深的元素时会非常方便。 你在Elements面板里这试试那试试时,用鼠标右键点击任何一个节点,看看会弹出些什么菜单。其中有一个菜单是“Break on Subtree Modifications(子树发生修改时暂停执行)”。 你选上它后,对鼠标下那个节点下的所有DOM节点进行修改时,浏览器会自动暂停,给你个调试的机会。 CSS的编辑 接下往右看,会看到CSS编辑器,它可是Inspector最有用的特性之一。粗浅说来,用它可以对你的CSS进行实时编辑。但是,它大大减少了试验所需克服的障碍,我发现我经常在该编辑器中挪东挪西,对各种想法进行试验。要不是它提供这么便利的试验条件,我那些想法可能早就因为被认为愚蠢到家而被直接抛弃了;正如Bret Victor 所说,这可是一件大好事。 右侧列表中你首先看到的是“Computed Style×(计算所得样式)”部分。选中“Show inherited(显示继承项)”检查框,你就能看到由左侧选中的节点所适用的所有样式属性极其取值组成的一个列表。 及时你没有显式地设置某个属性,它也会显示出它所继承的缺省值。 这样不仅仅可以帮你理解一个节点的样式到底是由哪些属性组成的,而且还可以帮你找出修改该节点样式所需设置的属性。请你看看那些属性中有没有你还不知道的属性,然后修改一下它看看它到底有什么作用。 列表中的下一项是“Styles(样式)”部分。在这部分将左侧选中的节点所适用的属性按照选择器进行分组显示。 第一个子部分标题是“element.style”,它显示的是在HTML中通过style=""设置的所有属性。接下来的子部分标题为“Matched CSS Rules(相匹配的CSS规则)”,显示的是同所选节点向匹配的选择器以及其中的属性和值,并且右侧还显示了选择器所在的文件名以及行号(line number)。 要添加新的选择器,可以点击“Styles”标题栏右侧的“+”按钮, 这里你可以定义选择器,适用tab键,书写属性及其值。你会发现,Chrome提供了自动补全建议(这是调查你能设置哪些属性的另一个很好的方法)。撰写本文时所用的最新版的Canary要求敲击右箭头键来完成自动补全动作,接下来可以按tab键并设置属性的值。再次敲击tab键就可以进行下一个属性设置了。如果你想在已有的选择器中设置一个新属性,点击一次结尾的括号然后点击“+”新选择器右边的按钮就能让你指定一个伪选择器了(a pseudo selector)。这真是太方便了! ![]() 所有这些都很好,但让我们假设一下,你已经花了10分钟对CSS进行了各种编辑,然后呢?你怎样保存这些修改呢?要保存修改,就要点击选择器的文件名(或者你自己到资源面板中找到相应的文件),接下来鼠标右击该文件(该文件将更新以反映那些修改操作),然后就可以点击“Save As”菜单覆盖你已有的文件了。个人经验,我发现选择文本并将其粘贴到我的编辑器中速度更快而且还不容易出错。 最后在CSS编辑方面要注意的一点是:如果你添加了新的选择器(通过敲击“+”键),那么该选择器不会被保存到文件中,因为Inspector不知道要将这个新选择器保存到哪个CSS文件中。
Metrics(尺寸大小)啧啧,一下子说了这么多内容!花点时间摆弄摆弄这些东西吧。摆弄的差不多了,我们就来看下一项内容:Metrics。如果你还不熟悉CSS的盒子模型(Box Model),那就先去看看这篇非常棒的指南。 Metrics部分显示的是浏览器是如何按照内容的尺寸、填充空间(padding)、边框(border)和边距(margin)来渲染(render)节点的。这个工具用来调试位置/尺寸问题。 Metrics面板有一个非常好用的小技巧,覆盖在所选节点之上的那个半透明的蓝色盒子可以用来显示出填充空间和边距,从而帮助你看明白盒子是如何影响流(flow)的。 ![]() 蓝色部分表示的是内容,绿色部分是填充空间,橘色部分是边距。 我们暂时先跳过属性和DOM断点这两个部分。我还没发现属性部分有什么用处,DOM断点显示的是鼠标右击节点后选定的各种“Break on …”动作。我们在Elements面板中最后要讨论的就是事件侦听器部分。 如果你为选中的节点添加了任何事件侦听器的话(用JavaSctip或者HTML的属性都可以添加),你就能在这里看到所有你所添加的侦听器。这个部分便于你想调试一个侦听器是否正确的添加到了某个节点上,还能帮你了解当侦听器得到调用后会发生什么。 单击小标题右侧的漏斗图标,可以在查看所选节点的侦听器和整个文档的侦听器之间进行切换。如果你的侦听器添加到了无法在主列表中进行选择的东西(比如window和document)上时,会非常有用。 你的HTML和CSS看起来表现不错,并且你写了不少的JavaScript代码,使用了文件系统API、IndexedDB、LocalStorage、应用缓冲区(App Cache)以及Cookies。资源面板就是用来让你所有这些存储资源进行检视和调试的。里面大部分的东西或多或少都几乎相同,也都相当的不言自明:单击一类资源就能看到一个项目(item)列表,一步步点击深入进去就可以找到你的数据。 里面的叫做“Frames”的第一项需要注意。它包含了你的应用中的所有frame,每个frame都按照图片、脚本和样式表分组列出所有资源。实际上,我深挖Frames列表的唯一的原因,就是去找我所编辑的样式表文件,然后把文件的内容拷贝粘贴到我们的编辑器中进行保存。 调试网络问题时,直接可以用网络面板。图片文件没有更新?网络面板会告诉你它是不是从缓存加载的。XHR(异步请求)没有响应?网络面板可以告诉你它被卡住或者出错。 点击“记录”按钮(黑色圆钮),在重新加载时将维护一个网络会话,如果你想看到代码的变化如何影响网络性能。 如果你在调试性能问题,网络面板很有帮助。在右侧,你可以看到网络请求的“级连瀑布流”。如果页面花费了非常长时间加载,调试的第一步应该是查看瀑布流。蓝色和红色的竖线显示DOMContentLoaded事件的时间,意味着在该时间点之前,用户一直在焦急的等待。你需要尽量减少该时间。 瀑布 有位客官问了,为什么我老把右边那部分内容叫做瀑布呢?噢,因为它的样子看上去和瀑布很像,但更重要的是,很像瀑布的原因在于,每次网络交互所花的时间包括网络延迟和文件下载所花的时间这个两个部分,而且在文件下载时,浏览器只能够并行下载一小部分文件。如果你的瀑布看上去很宽,那么你就需要改变一下方式,缩减HTML中HTTP请求的总数了。 还有,你可以通过点击“Timeline(时间线)”的标题栏得到一个下拉选择框来改变时间线的排序方式。特别值得关注的是按照“Latency(时延)”进行排序,就能够看到在所有请求中,建立连接所花的时间最长的是哪个请求。 ![]() 横条左侧半透明的部分显示的是时延,深色部分是文件下载所花的时间。 在网络面板的底部, 单击“XHR”可以只显示XMLHttpRequest所涉及的网络连接。随后再点击其中的一项,界面右侧显得的就变成了刚才点击的那个网络请求的细节性信息了。第一个标签下显示的是该网络请求过程中所发送的全部HTTP头部(header)以及响应信息。这些信息在调试服务器或者CORS的bug时非常有用。 Preview(预览)下显示的是格式化之后的响应信息。如果你获得的是大量JSON数据, 预览标签下它们就会以可折叠方式进行显示,而在响应标签下它们只是以普通文本的方式显示的。 Cookies显示的是网络请求过程中发送的所有cookies,时序信息(Timing)显示的是网络请求处理过程中的时间信息。时序信息在网络请求所花时间过长时同样也是很有用的。 我是一名专职的JavaScript开发人员,也就是说,在我工作当中的大部分时间我都花在这个面板上了。这个也是最近变化最大的面板之一。 环顾四周,这里有两个按钮有必要说一下。 “Pretty Print”按钮(看上去象一对花括号)用来对最小化(minified)的文件内容进行恰当的排版。如果你发现在第三方最小化的代码包中发现有一个bug而且还想搞清除bug的来龙去脉时,这个按钮将会非常有用。 另一个要说一下的是“Break on Exception”按钮(看上去象个暂停按钮)。如果它是灰色的,那么它就是处于禁用状态。单击该按钮就会让你的脚本在抛出任何异常时暂停执行。再单击一次该按钮,它就会处于 “Break on Uncaught Exception”模式,这时只有在脚本抛出的异常没有被捕获时才会暂停执行。这个按钮不可或缺,当你想要跟踪脚本抛出的异常时,它能保留住异常抛出时的调用栈以及应用当时的所有状态。 主要工作区中标签外带了一个完整的文件浏览器,以文件的来源对所有文件进行划分,这大大改善了到处胡乱文件的效率。 要打开文件浏览器,单击左上角那个奇怪的图标(用一个带直角拐弯的线连接起来的两个文件夹)。缺省情况下,文件浏览器会“漂浮”在工作区之上, 所以,你要单击一下文件浏览器右上角那个奇怪的图标(半白半黑的矩形),将文件浏览器停靠在工作区中。你可以试着在文件浏览器中敲几个键,它就能通过模糊匹配的方式定位到其中的文件! ![]() 既然说到在很多文件中查找想要的文件了,不得不再说一下,敲击“CMD+O”键会弹出一个TextMate风格的“Go-to-File”弹出式文件定位器,可以让你快速定位都一个文件。“CMD + Shift+ O”会弹出一个“Go-to-Symbol”弹出式符号定位器,可以让你快速地定位到当前文件中的一个符号。,“CMD + L”可以让你快速定位都某一行。 ![]()
断点 单击代码区左侧的侧边栏中的行号(line number)会插入一个断点。如果你的应用执行到了这一行代码,就会暂停执行后弹出脚本面板,并高亮显示本行代码。随后,你便可以查看调用栈,能够访问到的变量,还可以查看/修改对象。这个就是调试JavaScript代码问题的主要工作流程。 你偶尔可能会想调试热点代码(hot code,执行次数非常之多的代码)中出现的问题。这时插入断点就会非常麻烦,因为在执行过程中你不得不经常点击“Continue(继续执行)”按钮。通常在这种情况下,我会用类似“window.foo = true”和“window.foo = false”这样的条件来过滤想要调试的函数执行情况。鼠标右键点击断点,单击 “Edit Breakpoint(编辑断点)”菜单,就可以在文本输入框中输入“window.foo”。这是告诉Inspector,只有在window.foo取值为true的情况下才暂停执行。 ![]() 现在,你加好了断点,刷新了页面,脚本执行暂停了下来。接下来的事就会非常有意思了。 第一个要注意的是侧边栏的“Watched Expressions(受监视的表达式)”。如果你非常关系某些表达式的值 (比如“MyApp.someController.property === ‘some value’”),那就应该把它加入到“Watched Expressions”中,这样你就不用为了看它取的什么值而在控制台中一遍又一遍地输入这个表达式了。 接下来的“Scope Variables(可访问到的变量)”列出的是局部变量和全局变量。如果使用变量时用的是闭包,变量就会按照闭包进行分组显示。“Global”组列出的是“window”对象所具有的变量(这个列表可长了去了)。随着你不断的切换当前函数,这个变量列表也会随之自动更新。 既然你已经查看完了断点处你的应用的所有状态,接下来你可能想再看看别处的情况。“Continue(继续执行)”, “Step Over(单步跳过)”, “Step Into(单步进入)”以及“Step Out(单步跳出)”是你可以利用的几个好按钮。实际上,你使用它们的频率会非常之高,所以最好还是再次打开快捷键列表窗口,记住这几个按钮的快捷键。在这些列表中来来回回找东西用键盘可比用鼠标效率高多了。如果你以前就用过调试器,这些概念对你来说就不会陌生。但对于Web开发人员来讲,这些概念他们还是第一次接触。
在单步执行代码过程中定位bug或者找出代码的执行路线时。这几个都是必不可少的工具。 还有一个非常顺手的工具是在“XHR Breakpoints”部分。正如其名所示,它用来设置同XMLHttpReques对象相关的断点。这是通过在你想查看的URL中加入一个子字符串来指定断点的方法。非常好用! 还有,在“Scope Variables”部分,你可以右击一个函数然后选择“Jump to Definition”立即跳到定义该函数的文件中定义该函数的那段代码。 时间线面板(Timeline Panel) 下一个要讲的是时间线面板。你可以已经观察到了, 每个面板都是用来调试某一类的问题的。:元素( Elements)面板用于调试DOM和CSS方面的问题的,资源(Resources)面板用于本地存储和资源文件,网络(Network)面板用于HTTP请求,脚本(Scripts)面板用于Javascript。时间线(Timeline)面板用于调试浏览器性能方面的问题。 我所说的“浏览器性能”是什么意思?它所指的是一般都是不受你控制的东西,但它会影响你的应用的性能。对幕后发生的一切有所了解对开发日益复杂的应用来说,非常有必要。 首先要引起注意的是时间线部分。要激活时间线,就要单击“Record(记录)”按钮(在时间线面板的底端左边部分的黑色圆圈)。等它变成红色之后,就可以在你的应用中执行一个你想仔细观察的任务。如果你想弄明白为什么你的应用中滚动条滚动起来非常慢,你就可以慢慢滚动一下。如果你想弄清楚为什么你应用中的模态面板(modal panel)装载非常慢,那你就装载一次。不要担心你的动作涉及面太大后会导致时间线面板中显示的东西过多,这有几个工具能够帮你解决这个问题。 ![]() 现在你得到了你所关心的任务所产生的时间线,但你关心的其实是这些数据中的一小部分。想要“Zoom in(放大)”的话,你可以在时间线上部的图形上单击鼠标后进行拖拽。然后你就能看到两个调节线,通过拖拽调节线你可以调整下部可见内容的时间范围。然后看下面的瀑布图形,你会注意到有一些橘色的横条壮胶囊图形左边有一个小箭头。点击小箭头可以展开其中的内容,包含的是触发浏览器完成任务的函数调用。如下例所示,我们可以看到发生了一个滚动条scroll时间,调用了该时间的处理程序,从而产生了一个“Recalculate Style(重新计算显示样式)”事件。如果你把鼠标悬停到侧边栏中的某项内容后,你就能看到更多的细节。 ![]() 此时你可能会想知道,“那些占用了时间的紫色事件是什么意思?是重绘(Repaint)、重新计算显示样式(Recalculate Style)还是重新布局(layout)?”。这些都是浏览器对可视内容发生改变做出回应时发生的浏览器事件。例如,如果你改变了可视区域的大小尺寸或者滚动了一下滚动条,浏览器就需要做大量的工作,才能保证让所有一切看上去和你期待的情况相一致。你也可以在代码中自行调用这些事件,所以,花点时间对Inspector所显示的这些东西有所了解还是值得的,不要对DOM发生的变化想当然。 Recalculate Style(重新计算显示样式) ![]() 这个事件会在你对CSS的属性进行修改时发生。在上面的截屏中,你可以看到我两次执行了同一条命令。第一次执行时,浏览器要进行Recalculate Style、Layout以及Paint。在第二次就只剩Recalculate style了。这是什么情况? 因为这是一个刚刚载入的页面,还处于完全不可见状态,为一个未具style的div设置一个高度会导致该div中内容的布局发生变化 (Layout), 从而导致视觉显示上的变化 (Paint),最后就刷新了它样式(Recalculate Style)。第二次用同样的值执行相同的命令时,浏览器跳过了Paint和Layout,因为它们根本没有发生变化。注意这里面的顺序:Recalculate Style负责通知后继过程是否需要得到触发调用。 让我们回到空白的页面,然后给出div的宽度、高度和背景色,让它在屏幕上显示出真正的变化: ![]() 这次浏览器需要进行两次重绘,但只需要计算一次布局。这是因为在Recalculate Style这一步浏览器发现元素的位置/尺寸并没有发生变化,但背景色变了,所以浏览器跳过了一次布局计算。任何导致显示内容变化的事件都会导致浏览器进行一次重绘。 它经常被称为“Reflows”, 布局事件会使浏览器重新计算页面中个元素的位置。举个例子,假如你让一个图片处于浮动(float)状态,文字就会围绕到它的周围。如果你去除了float,浏览器就不得不对它周围的文字进行重新排版(re-flow)。Paul Irish做了一个非常棒的视频,描述了这种重新排版的情况并说明了如何避免这种情况发生。
![]() 要了解更多幕后发生的事情方面的细节内容,请参见这篇博文. 内存 现在看过了时间线并对你的应用进行了相应的优化,但你的应用在用过一段时间后还是会不时地出岔,有时运行缓慢,有时显示内容时断断续续。在时间线中你也已经看到了有很多“GC” (内存垃圾回收的缩写,GC会时不时的跑出来清理闲置的对象。) 事件发生,内存工具就是帮助你来解决这方面的问题的。 Tony Gentilcore写了一篇很不错的文章,介绍了如何查找并修复内存泄露问题,这篇文章你一定要拜读一下。下面我来简单概述一下这篇文章。 在侧边栏单击Memory,然后单击“record”按钮。此时就在你的应用中执行任务并观察内存的变化情况。下图所示是一个应用的内存简况(profile)图,该应用只是在每次发生鼠标移动事件时生成一个对象并丢弃该对象。: ![]() 典型的JavaScript代码的内存图样子就像锯齿:先是在GC运行前所占内存不断增加,然后GC就会适时回收闲置内存。在GC运行过几轮后,内存图就应该会比较平坦了。如果在每次GC运行的间隙图形一直都是朝上高走,那么这就是发生了内存泄漏。随着你的应用不断地吞噬越来越多的内存,其运行速度就会越来越慢,有的浏览器(MobileSafari)实际上会直接结束你的应用。 在图形的下面显示的是DOM节点和事件侦听器调用总数,这些数据非常有用。这些数据的含义都相当的不言自明。 最后再说说,假如你在将应用部署到了生产环境(in production)后,发现里面还有一个bug并在Inspector定位出了这个bug发生在哪里。你如何把这一情况告诉你的同事或开发人员?其实,完全可以不用弄静态的截屏,实际上你可以右击“Timelines”和“Memory”,将你调试过程保存下来,这样你就能够将真正的调试数据分享给别人了。这在团队工作中方便极了。 到现在为止,你开发的应用看上去和你想要的样子很吻合,HTTP请求的总数也降到了最小,但应用中让浏览器做了许多本不需要做的事。有些地方还不太对。所有的一切都是清清爽爽的,只有一个小地方不是这样。你也已经用时间线面板对它进行调试了,但还是没有发现什么有深度的细节性信息。看来运行慢不是浏览器的过,而是你的代码。 此时就是该Profiles面板上场大显身手的时候了。 JavaScript的CPU分析器(Profiler) 在分析面板中要做的第一类事情就是进行JS的CPU执行效率分析。这个描述高度概括了它的要测量的是什么:你的应用中哪些函数的运行时间最长。 选中Profile面板后单击“Start”按钮。随后你所作的动作都会被记录下来,直到你按下那个鲜艳的红色“Record”按钮才会停止记录(也可以单击“Stop”按钮)。一旦记录停止,分析器就会按顺序显示出记录期间所执行的所有函数以及每个函数执行所花的时间。你可能看到了列表顶端有个“(program)”这样的一项内容。那是用来显示WebKit干活时所花的时间。你不能再进一步查看它的内容了,而且对它也做不了什么事情(但是在时间线标签下应该可以帮你定位这方面的bug)。 除此之外,下图所示是典型的Profile面板的样子: ![]() 图中所示是对我的博客网站进行分析的结果,分析期间我打开了相册并多次打开/关闭了几张照片。 看起来这部分交互过程中最耗时的是设置curtain的透明度和getBoundingClientRect。要对应用的这部分交互过程进行优化,需要的正是这方面的信息。
CSS选择器分析器(CSS Selector Profiler) 使用CSS并不是没有代价。复杂的样式表从分析到计算再到最后应用,每一步都要花一些时间。CSS选择器分析器显示的是每个选择器同DOM节点匹配的次数,以及浏览器应用这些选择器时所花的时间。在具有很多同一类型div的比较复杂的应用中,对这些div应用样式所花的时间在应用从调入浏览器到完成装载的这段时间中占的比例相当大。 Heap Snapshot(堆快照) 这个是Inspector中最不好用的视图。不好用到我根本就没发现它有什么用处。看看这个例子: ![]() 据我所察,这个视图里有用信息的量是零。 还得提一下Tony Gentilcore的这篇文章,也许它能点亮你前行之路。 Audits(审计)面板 马上就要完工啦!最后要说的是Audits面板,它的作用基本上是在把应用部署到生产环境之前最后再给你一些性能方面的提醒。 实际上,它会对各种资源以及所有的HTTP请求进行检查,根据业界当前的最佳实践提出一些改进意见。例如,在我撰写本文时,我运行了一下Audit面板,它告诉我,为了让布局过程能快一点完成,我应该在HTML里指定图片的大小。提醒得太好了! 文中所有的小技巧都有详细的文档可看,你应该至少快速浏览一下那些文档。 结论我希望你已发现本文中至少有那么一部分信息能对你有用。迄今为止,我编写复杂的桌面以及移动设备Web应用有2年的时间了。为了解决各种不同类型的问题,我使用过本文所述的每一个面板。 如果我曲解了什么、漏掉了什么或者犯了什么错误,恳请告知。 |