前端技術-調試工具(下)


頁面制作之調試工具

五.Profiles

這個主要是做性能優化的,包括查看CPU執行時間與內存占用等。

例述如下:原文地址:http://www.smashingmagazine.com/2012/06/12/javascript-profiling-chrome-developer-tools/

你的網站正常運轉。現在我們來讓它運轉的更快。網站的性能由頁面載入速度和代碼執行效率決定。一些服務可以讓你的網站載入更快,比如壓縮JS和CDN,但是讓代碼執行的更快你要做的事情。
代碼中很小的改動都可能對性能造成巨大的影響。快速靈活的網站和可怕的“無響應腳本”對話框可能只有幾行代碼的差別。這篇文章告訴你如何通過用Chrome開發者工具(Chrome Developer Tools)找到這幾行關鍵的代碼。

我們來看一個簡單的“顏色排序器”應用,這個應用展示了一個由各種顏色構成的網格,你可以拖拽這些顏色進行混合。每一個點都是一個div標簽加上一些讓它看起來是圓的的CSS。

頁面載入的很快,但還是花費了一些時間,在渲染之前還閃了一下。是時候對這個頁面進行性能分析讓它更快了。

+設置一個基線

在開始做性能優化的時候要設置一個基線,來明確這個頁面的速度到底怎樣。這個基線可以讓你知道自己是否做了優化並幫助你權衡利弊。
性能分析器(profiler)是chrome開發者工具的一部分,點擊小扳手下面的工具菜單就可以打開它。Firebug也有一些性能評測工具,但是webkit內核的瀏覽器(chrome和safari)在對代碼進行性能分析和展示時間線方面是最棒的。Chrome還提供一種很棒的事件跟蹤工具,叫做 speed tracer。
在時間線(timeline)標簽下開始記錄,載入頁面然后停止記錄,這樣就設置了一個基線。(打開chrome開發者工具,點擊“時間線”標簽,然后點擊窗口底部圓形的黑色“記錄”圖標開始記錄)。我記錄了三次然后取了平均值,以防我的電腦在第一次測試的時候運行的很慢。

用chrome開發者工具進行JS性能分析

我的平均基線,也就是從第一個請求到頁面全部渲染結束所花費的時間是1.25秒。這個時間不是太長,但是對於這樣一個小的頁面來說也不算好。我想讓代碼執行的更快,但是我並不知道是什么讓它慢下來的。性能分析器(profiler)幫助我找到原因。

+創建一個Profile

時間線(timeline)告訴我們代碼運行花費的時間,但是並沒有幫助我們知道代碼運行的時候發生了什么。profiler告訴我們哪些函數的執行占用了大部分時間。讓我們切換到chrome開發者工具的“Profiles”標簽頁開始性能測試,這里一共提供了三種類型的性能測試。


1、javascript cpu 性能測試
顯示javascript占用了多少CPU

2、css選擇器性能測試
顯示處理CSS選擇器占用的CPU

3、堆棧快照
顯示javascript對象的內存占用情況

我們想要javascript代碼執行的更快,所以我們進行CPU性能測試。我們開始性能測試,刷新頁面然后停止。

用chrome開發者工具進行JS性能分析

通過性能分析首先知道很多函數在執行。我發現列表最頂端的是decimalToHex和makeColorSorter兩個函數。這兩個函數占用了CPU13.2%的時間,這是做優化的好地方。

我們可以點擊函數調用旁邊的“下一個”箭頭來查看完整的函數調用堆棧。展開后,可以看到decimalToHex是被makeColorSorter調用的,makeColorSorter是通過$(document).ready調用的。

$(document).ready(function() {
    makeColorSorter(.05, .05, .05, 0, 2, 4, 128, 127, 121);
    makeSortable();
});

弄清楚這兩個函數是哪里調用的,也就弄清楚了讓顏色可以排序並不是最大的性能問題。通常情況下性能問題都是由多余的排序操作造成的,但是在我的代碼中相比與排序增加DOM元素花費了更多時間。

我想要讓這些函數執行的更快,但是首先我想要將我的改動區隔開。在頁面載入過程中會發生很多事情,我不想要這些影響到我的性能分析。

+區隔問題

我做了第二個版本,這個版本中“顏色排序器”在我點擊按鈕之后才載入,而不是在document ready的時候載入。這就把文檔載入的過程分離出去,讓我可以只對顏色分類進行性能測試。調完性能之后我可以立刻改回去。讓我們調用新的函數testColorSorter並把它綁定到一個可點擊的按鈕上。

function testColorSorter() {
    makeColorSorter(.05, .05, .05, 0, 2, 4, 128, 127, 121);
    makeSortable();
}
1
<button id="clickMe" onclick="testColorSorter();">Click me</button>

在我們進行性能分析之前改變應用可能導致意外的結果。這個改動看起來很安全,但是我還是要重新運行性能檢測器來看看我是不是無意中改變了什么。我會開始一次新的性能分析,點擊應用中的按鈕然后停止。

用chrome開發者工具進行JS性能分析

我首先注意到decimalToHex函數的載入只占用了4.23%的時間。這是代碼執行花費時間最多的地方。我們創建一個新的基線來看看這個方案對代碼有多大的優化。

用chrome開發者工具進行JS性能分析

有些事件在我點擊按鈕之前有觸發了,但是我只關注從我點擊鼠標到瀏覽器渲染“顏色排序器”花費的時間。鼠標在390毫秒時點擊,渲染事件在726毫秒處被觸發。726減去390得到我的基線336毫秒。和第一個基線一樣我重復了3次來取平均值。

這時,我知道如何獲得並且得到了代碼確切的運行時間,我們已經准備好開始解決問題了。

+讓代碼更高效

性能分析器只告訴我們哪個函數造成的問題,所以我們要查看下函數的源碼來了解函數做了些什么。

function decimalToHex(d) {
    var hex = Number(d).toString(16);
    hex = "00".substr(0, 2 - hex.length) + hex; 
 
    console.log('converting ' + d + ' to ' + hex);
    return hex;
}

“顏色排序器”中的每一個顏色點都有一個16進制的色彩值,例如#86F01B和#2345FE.這些值表示一種顏色中紅,綠,藍三原色各自的數值。例如的背景色是#2456FE,代表紅色的值是36,綠色的值是86,藍色的是254,每一個數值必須是0到255之間的。

decimalToHex函數把這用RGB值表示的顏色轉化為頁面中我們使用的16進制顏色。這個函數十分的簡單,但是我還是留下了一個可以去掉的調試代碼console.log在那里。

decimalToHex 函數還在數字之前加上了補位。這是很重要的一點,因為有些10進制數字對應的是1個16進制數字。比如十進制中的10對應着16進制中的C,但是在CSS中需要一個兩位數。為了讓這個進制換算更快速,我們讓這段代碼不是那么泛化。我知道每個需要補位的數字長度都為1,所以我們可以這樣重寫這個函數。

function decimalToHex(d) {
    var hex = Number(d).toString(16);
    return hex.length === 1 ? '0' + hex : hex; }

第三個版本的“顏色排序器”只有在需要補位的時候才改變字符串,並且不用調用substr函數。有了這個新函數,運行時間是137毫秒。再次對代碼進行性能測試,可以發現decimalToHex函數只占用了總時間的%0.04,到了列表的下部。用chrome開發者工具進行JS性能分析

我們還可以發現占用CPU最多的函數是 jQuery的e.extend.merge。我不知道這個函數的作用,因為代碼是壓縮過的。我可以使用開發版本的jQuery,但是我發現這個函數是被makeColorSorter調用的。所以下一步我們先讓這個函數執行的更快。

+減小改動

“顏色排序器”中的多彩顏色是用過正弦曲線生成的。在光譜中設置一個中心點,然后以一定的偏移來創建這個曲線。這就把顏色變成了一個“彩虹模型”。我們還可以通過改變紅綠藍三原色的使用頻率來改變顏色。

function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {
 
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);
 
       console.log('red: ' + decimalToHex(red));
       console.log('green: ' + decimalToHex(green));
       console.log('blue: ' + decimalToHex(blue));
 
       var div = $('<div class="colorBlock"></div>');
       div.css('background-color', '#' + decimalToHex(red) + decimalToHex(green) + decimalToHex(blue));
       $('#colors').append(div);
 
    }
}

我們要去掉console.log函數。這些調用非常的糟糕,因為每次執行都會調用decimalToHex函數,這意味着decimalToHex函數會被多調用2倍的次數。這個函數大幅度的改變了DOM結構。每次循環,都向id為colors的div中添加一個新的div。這就讓我懷疑這就是e.extend.mergefunction做的事情。用性能分析器做一個小實驗就可以搞清楚。

我想要一次把所有的div添加進去,而不是在每個循環中添加一個新的div。創建一個變量來存儲數據,然后在最后一次性添加進去。

function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {
 
    var colors = "";
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);
 
       colors += '<div class="colorBlock" style="background-color: #' + 
           decimalToHex(red) + decimalToHex(green) + decimalToHex(blue) + '"></div>';
    }
 
    $('#colors').append(colors);
}

這個小改動意味着DOM只在添加所有div的時候做一次改變。用時間線進行測試,我們發現從點擊到渲染花費了31毫秒。這個dom變動,使得第四個版本的運行時間降低了86%。我可以再次打開性能分析器(profiler),發現e.extend.merge函數占用了很少的時間,在列表中已經看不到它了。

我們還可以完全移除decimalToHex函數讓代碼更快一點。因為CSS支持RGB顏色,所以我們不需要把他們轉換到16進制。現在我們可以這樣寫makeColorSorter函數。

function makeColorSorter(frequency1, frequency2, frequency3,
                         phase1, phase2, phase3,
                         center, width, len) {
 
    var colors = "";
    for (var i = 0; i < len; ++i)
    {
       var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center);
       var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center);
       var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center);
 
       colors += '<div class="colorBlock" style="background-color: rgb(' + 
           red + ',' + green + ',' + blue + ')"></div>';
    }
 
    $('#colors').append(colors);
}

第五個版本的執行只用了26毫秒而且代碼行數從28行減少到18行。

在你的應用中進行Javascript性能分析

實際工作中的應用要比“顏色排序器”復雜的多,但是做性能分析要遵循同樣的基本原則

1、設置一個基線,這樣你就知道你是從何處開始的。

2、把問題從應用的其他代碼隔離出來。

3、在一個可控的環境下進行優化,頻繁的使用時間線(timelines)和性能分析器(profiles)

還有一些性能優化的准則

1、從最慢的部分開始,這樣在時間優化上可以得到最大的提升。

2、控制環境。如果你換了電腦或者做了任何大的改動,都要設置新的基線。

3、多次分析以防你電腦的異常導致得到不正確的結果。

每個人都想要他的網站更快,你必須開發新的功能,但是新的功能通常會讓網站更慢。所以花費時間來做性能優化是有價值的。

六.Resource

資源面板展示了頁面中的所有資源。

image_thumb10_thumb

1、資源面板tab;
2、左側欄分類列出頁面資源。如“框架”、“session存儲”,如果前面有箭頭點擊展開還可以看到更多信息。注意左側欄的大小是可以調整的;
3、頁面資源包括字體、圖片、js、css和頁面本身。如果頁面中有frame或iframe,展開Frames會看到其對應的frame和iframe。頁面層次結構更清晰
4、數據庫顯示頁面相關的SQL數據庫數據信息;
5、相應IndexedDB 也展示頁面的IndexedDB 信息;
6、以鍵/值 形式列表展示本地存儲的數據;
7、以鍵/值列表顯示session存儲數據;
8、根據域名列舉cookie;
9、顯示通過manifest緩存的資源。包括很多信息,如js庫文件會顯示文件地址、大小和類型;
10、右側用來顯示每個資源對應的詳細信息。

雖然現在由frame組成的頁面越來越少見了,但查看框架內容的方法還是有必要了解的。下面截圖,是一個由frame組成的頁面。

image_thumb12_thumb

+每個frame都相關的資源都在一個文件夾下,同樣點擊展開可以了解頁面的資源、js、css、圖片文件和字體情況。點擊選中一個框架,頁面中其對應的區域會高亮顯示。
注:不會列出系統已有的,如“arial”“Helvetica”等,只會列出瀏覽器需要下載安裝的

+保存和查看資源

image_thumb131_thumb

+cookies

查看某個網站的cookie信息。如http://study.163.com/.

image_thumb17_thumb

[name]-字段名。如字段名為“remember_checked”,其值為1,這可能說明用戶在登陸的時候選擇了記住我;
[value]-字段所對應的值。如“_twitter_sess”所對應的值為一串加密了的session ID;
[domain]-cookie所在的域。上圖的“.twitter.com”表明其子域也是可以訪問該cookie的;
[path]-跟域相同,設置有效的路徑。設置為“/”表明允許所在路徑下都可以訪問cookie;
[expires]-瀏覽器可以刪除該cookie的日期;
[size]-cookie的大小,單位bytes;
[HTTP]-cookie的訪問允許HTTP協議。這可以防止跨站js獲取cookie攻擊;
[secure]]-只允許加密連接訪問cookie,如HTTPS;

+緩存應用

[resource]-資源的完整路徑。典型的資源包括靜態資源和html文件,manifest文件也屬於其中;
[type]-可以改變。Manifest文件的文件類型是Manifest,其他的manifest文件中定義的文件類型為explicit。Fallback類型的文件是那些需要回調資源文件的回調文件;
[size]-資源文件的大小,單位bytes;

七.Audits

用於優化前端頁面,加速網頁加載速度等。

使用Chrome瀏覽器對頁面性能進行檢測,根據測試的結果進行優化。當然這個結果只是參考,在實際的項目中肯定有特殊情況存在,並不能為了滿足某項測試結果而忽略特定情況的存在。

1、Chrome檢測工具

點擊Audits然后出現了如下界面,選中重載頁面開始檢測按鈕,然后點擊Run按鈕,之后就是等待結果。

image_thumb22_thumb

2、檢測結果

這個檢測結果分為2類,一個是網絡,一個是網頁性能;

檢測結果不僅列出了問題,還定位問題在哪里,可以很快入手解決對應的問題。

1)合並JS文件:Combine external JavaScript(總共有29個可以壓縮的JS文件)
2)There are multiple resources served from same domain. Consider combining them into as few files as possible.一個域名有多個文件,可以考慮將他們壓縮為盡可能少的文件。

3)

4)啟用gzip壓縮:Enable gzip compression
5)Compressing the following resources with gzip could reduce their transfer size by about two thirds (~715 B).啟用gzip壓縮降低傳輸大小。

image_thumb26_thumb

6)

image_thumb29_thumb

7)瀏覽器緩存:Leverage browser caching
8)The following resources are missing a cache expiration. Resources that do not specify an expiration may not be cached by browsers。資源沒有指定過期時間,瀏覽器可能不會緩存。

網頁性能部分
1)優化樣式和腳本的順序:Optimize the order of styles and scripts (4)

2)把CSS放到head中:Put CSS in the document head (3)
CSS in the document body adversely impacts rendering performance.

3)刪除沒用的CSS:Remove unused CSS rules (44)
44 rules (19%) of CSS not used by the current page.

4)Use normal CSS property names instead of vendor-prefixed ones (3)

應用:自己Css代碼的審核;下載復制別人代碼,去除無用的Css樣式。可以使用FireFox的Dust-Me selectors去除無用的Css樣式。

八.Console

1.console.log

大家都會用log,但鮮有人很好地利用console.error , console.warn 等將輸出到控制台的信息進行分類整理。
他們功能區別不大,意義在於將輸出到控制台的信息進行歸類,或者說讓它們更語義化。
各個所代表的語義如下:

console.log:普通信息
console.info:提示類信息
console.error:錯誤信息
console.warn:警示信息

當合理使用上述log方法后,可以很方便地在控制台選擇查看特定類型的信息。

image_thumb33_thumb

如果再配合console.group 與console.groupEnd,可以將這種分類管理的思想發揮到極致。這適合於在開發一個規模很大模塊很多很復雜的Web APP時,將各自的log信息分組到以各自命名空間為名稱的組里面。

image_thumb37_thumb

console.log第一個參數可以包含一些格式化的指令比如%c,給hello word加了很炫的樣式(全是純CSS用來控制樣式的):

如果還不夠過癮,那咱們來log一些圖片:

jdfw_thumb5_thumb1

除此,console.table 更是直接以表格的形式將數據輸出,不能贊得太多!

var data = [{'品名': 'X', '數量': 4}, {'品名': 'Y', '數量': 3}];
console.table(data);

image_thumb41_thumb

2.console.assert

當你想代碼滿足某些條件時才輸出信息到控制台,那么你大可不必寫if或者三元表達式來達到目的,cosole.assert便是這樣場景下一種很好的工具,它會先對傳入的表達式進行斷言,只有表達式為假時才輸出相應信息到控制台。

image_thumb45_thumb

3.console.count

除了條件輸出的場景,還有常見的場景是計數。
當你想統計某段代碼執行了多少次時也大可不必自己去寫相關邏輯,內置的console.count可以很地勝任這樣的任務。

image_thumb50_thumb

4.console.dir

將DOM結點以JavaScript對象的形式輸出到控制台
而console.log是直接將該DOM結點以DOM樹的結構進行輸出,與在元素審查時看到的結構是一致的。不同的展現形式,同樣的優雅,各種體位任君選擇反正就是方便與體貼。

image_thumb63_thumb

5.console.time & console.timeEnd

輸出一些調試信息是控制台最常用的功能,當然,它的功能遠不止於此。當做一些性能測試時,同樣可以在這里很方便地進行。
比如需要考量一段代碼執行的耗時情況時,可以用console.time與 console.timeEnd來做此事。

這里借用官方文檔的例子:

image_thumb60_thumb

當然,我們也可以選擇自己寫代碼來計時:

image_thumb59_thumb

6.console.profile & console.timeLime

當想要查看CPU使用相關的信息時,可以使用console.profile配合 console.profileEnd來完成這個需求。
這一功能可以通過UI界面來完成,Chrome 開發者工具里面有個tab便是Profile。

與此類似的功能還有console.timeLine配合 console.timeLineEnd,它的作用是開始記錄一段時間軸,同樣可以通過Chrome開發者工具里的Timeline 標簽來進行相應操作。

所以在我看來這兩個方法有點雞肋,因為都可以通過操作界面來完成。但至少他提供了一種命令行方式的交互,還是多了種姿勢供選擇吧。

7.console.trace

堆棧跟蹤相關的調試可以使用console.trace。這個同樣可以通過UI界面完成。當代碼被打斷點后,可以在Call Stack面板中查看相關堆棧信息。

上面介紹的都是掛在window.console這個對象下面的方法,統稱為Console API,接下來的這些方法確切地說應該叫命令,是Chrome內置提供,在控制台中使用的,他們統稱為Command Line API。

$

似乎美刀總是被程序員及各種編程語言所青睞「你看看PHP代碼就知道PHPer有多愛錢了」,在Chrome的控制台里,$用處還真是蠻多且方便的。
$_命令返回最近一次表達式執行的結果,功能跟按向上的方向鍵再回車是一樣的,但它可以做為一個變量使用在你接下來的表達式中:

image_thumb66_thumb

上面的$_需要領悟其奧義才能使用得當,而$0~$4則代表了最近5個你選擇過的DOM節點。
什么意思?在頁面右擊選擇審查元素,然后在彈出來的DOM結點樹上面隨便點選,這些被點過的節點會被記錄下來,而$0會返回最近一次點選的DOM結點,以此類推,$1返回的是上上次點選的DOM節點,最多保存了5個,如果不夠5個,則返回undefined。

另外值得一贊的是,Chrome 控制台中原生支持類jQuery的選擇器,也就是說你可以用$加上熟悉的css選擇器來選擇DOM節點

image_thumb69_thumb

$(selector)返回的是滿足選擇條件的首個DOM元素。
剝去她偽善的外衣,其實$(selector)是原生JavaScript document.querySelector() 的封裝。
同時另一個命令$$(selector)返回的是所有滿足選擇條件的元素的一個集合,是對document.querySelectorAll() 的封裝。

copy

通過此命令可以將在控制台獲取到的內容復制到剪貼板。

copy(document.body);

keys & values

這是一對基友。前者返回傳入對象所有屬性名組成的數據,后者返回所有屬性值組成的數組。具體請看下面的例子:

image_thumb71_thumb

monitor & unmonitor

monitor(function),它接收一個函數名作為參數,比如function a,每次a被執行了,都會在控制台輸出一條信息,里面包含了函數的名稱a及執行時所傳入的參數。

而unmonitor(function)便是用來停止這一監聽。

jdfw_thumb11_thumb1

debug & undebug

debug同樣也是接收一個函數名作為參數。當該函數執行時自動斷下來以供調試,類似於在該函數的入口處打了個斷點,可以通過debugger來做到,同時也可以通過在Chrome開發者工具里找到相應源碼然后手動打斷點。
而undebug 則是解除該斷點。

而其他還有好些命令則讓人沒有說的欲望,因為好些都可以通過Chrome開發者工具的UI界面來操作並且比用在控制台輸入要方便。

移動設備模式

現在很多的網頁都要適配移動端,Chrome的移動設備模式對開發者來說無疑是一個很大的驚喜。

點擊image_thumb_thumb,可以模擬各種各樣的移動設備

image_thumb7_thumb

拖動模擬屏幕的標記的兩塊東西能任意調節設備屏幕大小

頂部橙色部分的選項,這個是選擇各種要模擬的設備

下面的是當前設備的顯示屏像素

image_thumb1
去掉前面的勾,或者點擊這個刪除的按鈕,網頁將會回到你現在的瀏覽器顯示大小

image_thumb2[1]
點這個還能快速切換橫屏豎屏

image_thumb3
這個是當前模擬的設備的像素比,例如:iPhone3GS是1、iphone4是2、iPhone6是3....

image_thumb4
如果你在操作的時候遇到這個警告,那么你需要刷新下網頁才能看到實際的顯示效果

image_thumb6

這里的這個Fit是如果你選擇的模擬設備像素的顯示范圍超過了你的瀏覽器框框,那么就會根據你當前的顯示器高度和寬度自適應的縮放顯示比例。去掉勾選就是實際像素的顯示了。

image_thumb7[1]

然后我們來看看右邊藍色的部分 第一個Network是用來模擬網絡環境的。你可以模擬各種網絡環境以測試網頁的加載速度,甚至可以模擬斷網的狀態...

image_thumb8_thumb

移動設備模式暫時就介紹到這里。

---------------------------------------------------

就像開始說的,最主要的是自己多打開調試工具多點點,相信用多了就會熟悉。

轉載需注明轉載字樣,標注原作者和原博文地址。

前端技術-調試工具(上)

更多閱讀:

http://segmentfault.com/a/1190000000683599

http://www.ibm.com/developerworks/cn/web/1410_wangcy_chromejs/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM