前端技術演進(一):Web前端技術基礎

姜小抖發表於2019-03-04
這個來自之前做的培訓,刪減了一些業務相關的,參考了很多資料(參考資料列表),謝謝前輩們,麼麼噠 ?

每個開發者或多或少都接觸過前端,但現在的前端變化有點快,這裡是截至2018年的前端,暫且叫:現代前端技術演進。

網際網路資訊呈現的方式主要依靠終端裝置螢幕,如今,終端裝置的種類越來越多,智慧化越來越高,互動也越來越複雜。

image.png | center | 827x411.29466666666667

蘋果官網的演進

1992年:

image.png | left | 469x240

1996年:

image.png | left | 683x427

1998年:

image.png | left | 683x427

1999年:

image.png | left | 683x427

2000年:

image.png | left | 550x436

2001年:

image.png | left | 683x427

2003年:

image.png | left | 683x427

2005年:

image.png | left | 480x407

2006年:

image.png | left | 827x516.875

2007年:

image.png | left | 827x516.875

2008年:

image.png | left | 827x516.875

2010年:

image.png | left | 827x516.875

2011年:

image.png | left | 827x516.875

賈伯斯去世:

image.png | left | 827x516.875

2012年:

image.png | left | 827x516.875

2013年:

image.png | left | 827x516.875

2014年:

image.png | left | 827x516.875

2015年:

image.png | left | 827x516.875

2016年:

image.png | left | 827x385.4697845507094

2017年:

image.png | left | 827x462.73704520396916

2018年:

image.png | center | 827x562

蘋果的發展是IT行業的縮影,包含了工業設計、產品設計、硬體技術、使用者體驗、UI設計、前端技術等方方面面。

僅從前端來看,通過蘋果官網的演進,可以看到,隨著網際網路和移動網際網路的快速發展,前端技術也發生了巨大的變化。

前端應用開發模式演變

1、靜態黃頁
2、伺服器組裝資料的動態網頁
3、後端為主的 MVC
4、前後端分離
5、前端 MV* 框架
6、前端 VIrtual DOM,MNV*,前後端同構

image.png | center | 827x308.0575

所有變化,都是圍繞提升前端開發的效率和質量。

瀏覽器基礎

前端大部分時間都是在和瀏覽器打交道,所以我們先從瀏覽器說起。

從一個常見的前端面試題說起:

從我們開啟瀏覽器輸入一個網址到頁面展示網頁內容這段時間內,瀏覽器和服務端都發生了什麼事情?

這個問題也有一種發散性更強的說法是:從我們開啟瀏覽器輸入一個網址到頁面展示網頁內容這段時間內,都發生了什麼事情?比如下面是百度FEX(Web 前端研發部)的面試題:

image.png | center | 827x435

github.com/fex-team/in…

越詳細越好,有人可能從移動光電滑鼠說起:發光二極體發出的光線照亮滑鼠底部表面,然後將滑鼠底部表面反射回的一部分光線,經過一組光學透鏡,傳輸到一個光感應器件內成像,當滑鼠移動時,其移動軌跡便會被記錄為一組高速拍攝的連貫影象,通過DSP分析影象,就可以判斷滑鼠的移動方向和移動距離,從而完成游標的定位。。。從滑鼠鍵盤螢幕計算機、輸入輸出、作業系統、編譯原理啥的說起,可以說一天,所以這裡只關注瀏覽器和服務端主要的過程。

一個簡化的過程是這樣的:

  1. 在接收到使用者輸入的網址後,瀏覽器會開啟一個執行緒來處理這個請求,對使用者輸入的URL地址進行分析判斷,如果是HTTP協議就按照HTTP方式來處理。
  2. 呼叫瀏覽器引擎中的對應方法,比如WebView中的loadUrl方法,分析並載入這個URL地址。
  3. 通過DNS解析獲取該網站地址對應的IP地址,查詢完成後連同瀏覽器的Cookie、userAgent等資訊向網站目的IP發出請求。
  4. 進行HTTP協議會話,瀏覽器客戶端向Web伺服器傳送報文。
  5. 進入網站後臺上的Web伺服器處理請求,如Apache、Tomcat、Nginx、Node.js 等伺服器。
  6. 進入部署好的後端應用,如PHP、Java、 JavaScript、 Python 等後端程式,找到對應的請求處理邏輯,這期間可能會讀取伺服器快取或查詢資料庫等。
  7. 伺服器處理請求並返回響應報文,此時如果瀏覽器訪問過該頁面,快取上有對應資源,會與伺服器最後修改記錄對比,一致則返回304,否則返回200和對應的內容。
  8. 瀏覽器開始下載HTML文件(響應報頭狀態碼為200時)或者從本地快取讀取檔案內容(瀏覽器快取有效或響應報頭狀態碼為304時)。
  9. 瀏覽器根據下載接收到的HTML檔案解析結構建立DOM文件樹,並根據HTML中的標記請求下載指定的MIME型別檔案(如CSS、JavaScript 指令碼等),同時設定快取等內容。
  10. 頁面開始解析渲染DOM、CSS根據規則解析並結合DOM文件樹進行網頁內容佈局和繪製渲染,JavaScript 根據DOM API操作DOM,並讀取瀏覽器快取、執行事件繫結等,頁面整個展示過程完成。

下圖是在服務端的一些展開:

image.png | center | 827x551.3333333333333

作為前端,重點會關注這個過程中位址列輸入、網路請求、瀏覽器文件解析、渲染引擎、Javascript執行引擎,客戶端儲存等部分。所以我們先了解一下瀏覽器:

瀏覽器通常由如下七個部分組成:

image.png | center | 500x339

  1. 使用者介面(User Interface): 包括位址列、前進/後退按鈕、書籤選單等。除了瀏覽器主視窗顯示請求的頁面外,其他顯示的各個部分都屬於使用者介面。
  2. 瀏覽器引擎(Browser engine): 在使用者介面和呈現引擎之間傳送指令,或者在客戶端本地快取中讀寫資料等,是瀏覽器中各個部分之間相互通訊的核心。
  3. 呈現(渲染)引擎(Rendering engine): 負責顯示請求的內容,並將內容排版到瀏覽器中顯示成有樣式的介面。如果請求的內容是 HTML,它就負責解析 HTML 和 CSS 內容,並將解析後的內容顯示在螢幕上,也叫排版引擎,常說的瀏覽器核心一般也主要是指呈現引擎。
  4. 網路功能模組(Networking): 用於網路呼叫,比如 HTTP 請求。它的介面與平臺無關,併為所有平臺提供底層實現。
  5. 使用者介面後端(UI Backend): 用於繪製基本的視窗小部件,比如組合框和視窗。它公開了與平臺無關的通用介面,而在底層使用作業系統的使用者介面方法。
  6. JavaScript 直譯器(Javascript Interpreter): 用於解析和執行 JavaScript 程式碼。
  7. 資料儲存(Data Persistence): 持久層。瀏覽器需要在硬碟上儲存各種資料,例如 Cookie、localStorage。新的 HTML 規範 (HTML5) 定義了“網路資料庫”,這是一個完整(但是輕便)的瀏覽器內資料庫。

瀏覽器呈現引擎簡介

呈現引擎的作用嘛...當然就是“呈現”了,也就是在瀏覽器的螢幕上顯示請求的內容。

目前,主流的瀏覽器核心有4類:

  • Trident:IE、360、搜狗等;
  • Gecko:Netscape、Firefox等;
  • Presto:Opera(新的 Opera 使用了 Blink 核心,是 Webkit 的一個分支,新增了一些優化特性);
  • Webkit:Safari、Chrome

呈現引擎一開始會從網路層獲取請求文件的內容(內容的大小一般限制在 8000 個塊以內)。

然後進行如下所示的基本流程:

image.png | center | 600x66

  1. 解析HTML構建DOM樹時呈現引擎會先將HTML元素標籤解析成由多個DOM元素物件節點組成的且具有節點父子關係的DOM樹結構(DOM tree)
  2. 然後根據DOM樹結構的每個節點順序提取計算使用的CSS規則,並重新計算DOM樹結構的樣式資料,生成一個帶樣式描述的DOM渲染樹(render tree)物件。
  3. DOM渲染樹生成結束後,進入渲染樹的佈局(Layout)階段,即根據每個渲染樹節點在頁面中的大小和位置,將節點固定到頁面的對應位置上,這個階段主要是元素的佈局屬性(例如position、float、margin 等屬性)生效,即在瀏覽器中繪製頁面上元素節點的位置。
  4. 接下來就是繪製階段,將渲染樹節點的背景、顏色、文字等樣式資訊應用到每個節點上,這個階段主要是元素的內部顯示樣式(例如color、background. text-shadow 等屬性)生效,最終完成整個DOM在頁面上的繪製(Painting)顯示。

這是一個漸進的過程。為達到更好的使用者體驗,呈現引擎會力求儘快將內容顯示在螢幕上。它不必等到整個 HTML 文件解析完畢之後,就會開始構建呈現樹和設定佈局。在不斷接收和處理來自網路的其餘內容的同時,呈現引擎會將部分內容解析並顯示出來。

image.png | center | 624x289

Webkit主流程

image.png | center | 624x290

Gecko主流程

兩種呈現引擎工作流程的主要區別在於解析HTML或CSS文件生成呈現樹的過程:

  • Webkit 核心中的HTML和CSS解析可以認為是並行的;
  • Gecko 則是先解析HTML,生成內容槽 (Content Sink)後再開始解析CSS。

這兩種呈現引擎工作過程中使用的描述術語也不一樣:

  • Webkit 核心解析後的渲染物件被稱為呈現樹(Render Tree),由“呈現物件”組成;
  • Gecko 核心解析後的渲染物件則稱為Frame樹(Frame Tree),每個元素都是一個框架。

對於元素的放置:

  • WebKit 使用的術語是“佈局(Layout)”;
  • Gecko 使用的術語是“重排(Reflow)”。

但是它們主要的流程是相似的,都經過HTML DOM解析、CSS樣式解析、呈現樹生成和呈現樹繪製顯示階段。一般呈現引擎的解析過程中都包含了HTML解析和CSS解析階段,這也是呈現引擎解析流程中最重要的兩個部分。

什麼是解析

解析文件是指將文件轉化成為有意義的結構,也就是可讓程式碼理解和使用的結構。解析得到的結果通常是代表了文件結構的節點樹,它稱作解析樹或者語法樹。

比如:2 + 3 - 1 解析後會變成下面的樹:

image.png | center | 400x155

解析的過程可以分成兩個子過程:詞法分析(lexer)和語法分析(parser)。簡單來說,一個是拆分標記,一個是匹配規則。

image.png | center | 101x300

一般都會用一些工具來生成解析器,Webkit 用了兩個知名的解析器生成器:詞法分析器 Flex ,語法分析器 Bison(Lex/Yacc)。

HTML文件解析

<html>
  <body>
    <p>
      Hello World
    </p>
    <div> <img src="example.png"/></div>
  </body>
</html>複製程式碼

會被翻譯成如下的DOM樹:

image.png | center | 400x219

HTML的解析規則比較複雜,因為HTML有很高的容錯性,比如:

</br><br><br /> 都要解析成空行;

<table>
    <table>
        <tr><td>inner table</td></tr>
    </table>
    <tr><td>outer table</td></tr>
</table>

<!-- 離散表格會被解析成 -->

<table>
    <tr><td>outer table</td></tr>
</table>
<table>
    <tr><td>inner table</td></tr>
</table>複製程式碼

CSS解析

Webkit會把CSS檔案解析成 StyleSheet 物件,每個物件都包含CSS規則,CSS 規則物件則包含選擇器和宣告物件,以及其他與 CSS 語法對應的物件。

image.png | center | 500x393

一個節點上如果有多條不同的樣式規則,會通過權重的方式來計算。一般認為是:

!important > 內聯樣式規則 > id選擇器 > 類選擇器 > 元素選擇器

在 DOM 樹構建的同時,瀏覽器還會構建另一個樹結構:呈現樹。這是由視覺化元素按照其顯示順序而組成的樹,也是文件的視覺化表示。它的作用是按照正確的順序繪製內容。

image.png | center | 731x396

佈局

呈現器在建立完成並新增到呈現樹時,並不包含位置和大小資訊。計算這些值的過程稱為佈局(layout)或重排(reflow)。

佈局是一個遞迴的過程。它從根呈現器(對應於 HTML 文件的 <html> 元素)開始,然後遞迴遍歷部分或所有的框架層次結構,為每一個需要計算的呈現器計算幾何資訊。

佈局分為全域性佈局和增量佈局。全域性佈局是指觸發了整個呈現樹範圍的佈局,觸發原因可能包括:

  • 影響所有呈現器的全域性樣式更改,例如字型大小更改。
  • 螢幕大小調整。

增量佈局是隻對改變的部分(dirty呈現器)進行佈局。

繪製

在繪製階段,系統會遍歷呈現樹,並呼叫呈現器的“paint”方法,將呈現器的內容顯示在螢幕上。

和佈局一樣,繪製也分為全域性(繪製整個呈現樹)和增量兩種。

在發生變化時,瀏覽器會盡可能做出最小的響應。因此,元素的顏色改變後,只會對該元素進行重繪(repaint)。元素的位置改變後,只會對該元素及其子元素(可能還有同級元素)進行佈局(layout)和重繪(repaint)。新增 DOM 節點後,會對該節點進行佈局(layout)和重繪(repaint)。一些重大變化(例如增大“html”元素的字型)會導致快取無效,使得整個呈現樹都會進行重新佈局(relayout)和繪製(repaint)。

瀏覽器資料持久化儲存

瀏覽器快取(Browser Caching)是瀏覽器端用於在本地儲存資料並進行快速讀取,以避免重複資源請求的傳輸機制的統稱。有效的快取可以避免重複的網路資源請求並讓瀏覽器快速地響應使用者操作,提高頁面內容的載入速度。瀏覽器端快取的實現機制種類較多,一般可以分為九種:

  • HTTP檔案快取
  • LocalStorage
  • SessionStorage
  • indexDB
  • Web SQL
  • Cookie
  • CacheStorage
  • Application Cache
  • Flash快取

圖片描述

HTTP檔案快取

HTTP檔案快取是基於HTTP協議的瀏覽器端檔案級快取機制。在檔案重複請求的情況下,瀏覽器可以根據HTTP響應的協議頭資訊判斷是從伺服器端請求檔案還是從本地讀取檔案,Chrome控制檯下的Frames就可以檢視瀏覽器的HTTP檔案資源快取列表內容。

HTTP檔案快取處理的流程圖如下:

image.png | center | 747x464

比如:

image.png | center | 400x528.8000000000001

如果同時設定了 Expires 和 Cache-Control,則只有 Cache-Control 生效。

image.png | center | 500x553.5279805352799

localStorage

localStorage 是HTML5的一種本地快取方案。支援目前的主流瀏覽器,在不同瀏覽器中的長度限制各不相同,比如 Chrome 是 2.6MB,IE 是 5MB,這個長度限制是指單個域名下的 localStorage 大小限制。

image.png | left | 827x291

localStorage 不適合存放太多的資料,它遵循同源策略,但是它是持續存在的。

當瀏覽器進入隱私瀏覽模式,會建立一個新的、臨時的資料庫來儲存localStorage的資料;當關閉隱私瀏覽模式時,該資料庫將被清空並丟棄。

sessionStorage

sessionStorage 和 localStorage 類似,不過 sessionStorage 在瀏覽器關閉時會自動清空。用到的比較少,比如可以自動儲存表單輸入框的內容,如果瀏覽器因偶然因素被重新整理了,輸入框裡面的內容會被恢復,因此寫入的內容不會丟失。

Cookie

Cookie是伺服器傳送到使用者瀏覽器並儲存在本地的一小塊資料,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶併傳送到伺服器上。一條Cookie記錄主要由鍵、值、域、過期時間和大小組成,一般用於儲存使用者網站認證資訊或個性化設定。Cookie 最大長度限制一般為 4KB。

持久型Cookie會儲存在使用者的硬碟上。

image.png | center | 827x264.6714150047483

WebSQL

WebSQL是獨立於HTML5的單獨規範,現在支援的瀏覽器很少,所以用的不多。

WebSQL允許用SQL語句進行查詢,相當於整合在瀏覽器裡的小型資料庫。

image.png | center | 827x404.0266253869969

IndexDB

IndexDB支援的瀏覽器比較廣泛,一般推薦使用IndexDB來進行大量資料的儲存。瀏覽器對IndexDB的大小限制通常約為50MB。

DEMO:girliemac.com/stickies/

Application Cache

Application Cache 是一種允許瀏覽器通過manifest 配置檔案在本地有選擇性地儲存JavaScript、CSS、圖片等靜態資源的檔案級快取機制。當頁面不是首次開啟時,通過一個特定的manifest檔案配置描述來選擇讀取本地Application Cache裡面的檔案。
.
使用Application Cache來實現瀏覽器應用具有以下三個優勢。

  1. 離線瀏覽:通過manifest配置描述來讀取本地檔案,使用者可在離線時瀏覽完整的頁面內容。
  2. 快速載入:由於快取資源為本地資源,因此頁面載入速度較快。
  3. 伺服器負載小:只有在檔案資源更新時,瀏覽器才會從伺服器端下載,這樣就減小了伺服器資源請求的壓力。

image.png | center | 827x327.6083995459705

Application Cache 已經開始慢慢被棄用,被 Service Worker 取代。

cacheStorage

cacheStorage是在ServiceWorker規範中定義的,可用於儲存每個ServiceWorker宣告的Cache物件,是未來可能用來代替Application Cache的離線方案。

示例程式碼:

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('mysite-static-v3').then(function(cache) {
      return cache.addAll([
        '/css/whatever-v3.css',
        '/css/imgs/sprites-v6.png',
        '/css/fonts/whatever-v8.woff',
        '/js/all-min-v4.js'
        // etc
      ]);
    })
  );
});複製程式碼

演示:fed.renren.com/

具體使用可以參考:developers.google.com/web/fundame…

前端除錯工具——Chrome 開發者工具

Chrome 開發者工具是一套內建於Google Chrome中的Web開發和除錯工具,可用來對網站進行迭代、除錯和分析,是前端開發人員最常用的除錯工具之一。

元素皮膚(Elements)

使用 Chrome DevTools 的 Elements 皮膚檢查和實時編輯頁面的 HTML 與 CSS。

image.png | center | 747x433

? 演示:

  • 實時編輯DOM節點;
  • 檢視元素事件偵聽器;
  • 實時編輯樣式;
  • 檢查和編輯盒模型引數;
  • 檢視本地更改;
  • 切換 Device Mode
  • 模擬感測器

控制檯皮膚(Console)

控制檯主要是用來檢視動態資訊和執行Javascript程式碼。

使用 Console API 可以向控制檯寫入資訊、建立 JavaScript 配置檔案,以及啟動除錯會話。

  • console.log
  • console.info
  • console.warn
  • console.error
  • console.assert
  • console.count
  • console.time
  • console.timeEnd
  • console.timeStamp
  • console.group
  • console.groupEnd
  • console.profile
  • console.profileEnd
  • console.trace
  • console.clear

? 演示:

console.time("Array initialize");
var array= new Array(1000000);
for (var i = array.length - 1; i >= 0; i--) {
    array[i] = new Object();
};
console.timeEnd("Array initialize");複製程式碼
var user = "jsmith", authenticated = false;
console.group("Authentication phase");
console.log("Authenticating user '%s'", user);
// authentication code here...
if (!authenticated) {
    console.log("User '%s' not authenticated.", user)
}
console.groupEnd();複製程式碼
function add(num) {
    if(num > 0) {
        console.trace('num:', num);
        return num + add(num - 1);
    } else {
        return 0;
    }
}
add(5);複製程式碼

便捷函式:

  • $_ 返回最近評估的表示式的值。
  • $(selector) <span data-type="color" style="color:rgb(33, 33, 33)">返回帶有指定的 CSS 選擇器的第一個 DOM 元素的引用。</span>
  • $$(selector) 返回與給定 CSS 選擇器匹配的元素陣列。

一些有趣的console:
www.zhihu.com/
www.tmall.com/
www.baidu.com/
www.iqiyi.com/

原始碼皮膚(Sources)

原始碼皮膚主要是用來檢視和除錯程式碼。

image.png | center | 827x394

? 演示:googlechrome.github.io/devtools-sa…

網路皮膚(Network)

我們的開發很多都是基於HTTP介面的除錯,所以網路皮膚非常重要。

Network 皮膚記錄頁面上每個網路操作的相關資訊,包括詳細的耗時資料、HTTP 請求與響應標頭和 Cookie等等。

Network 皮膚由五個窗格組成:

image.png | center | 827x423

  1. Controls。使用這些選項可以控制 Network 皮膚的外觀和功能。
  2. Filters。 使用這些選項可以控制在 Requests Table 中顯示哪些資源。按住 Cmd (Mac) 或 Ctrl (Windows/Linux) 並點選過濾器可以同時選擇多個過濾器。
  3. Overview。 此圖表顯示了資源檢索時間的時間線。如果看到多條豎線堆疊在一起,則說明這些資源被同時檢索。
  4. Requests Table。 此表格列出了檢索的每一個資源。 預設情況下,此表格按時間順序排序,最早的資源在頂部。點選資源的名稱可以顯示更多資訊。 提示:右鍵點選 Timeline 以外的任何一個表格標題可以新增或移除資訊列。
  5. Summary。 此窗格可以一目瞭然地檢視請求總數、傳輸的資料量和載入時間。

Network 皮膚可以在頁面載入期間捕捉螢幕截圖。此功能稱為幻燈片。

Network 皮膚突出顯示兩種事件:DOMContentLoaded 和 load。解析頁面的初始標記時會觸發 DOMContentLoaded。頁面完全載入時將觸發 load。

? 演示:皮膚、幻燈片

Filter 文字欄位還支援各種關鍵詞,Ctrl+空格可以檢視所有命令:

  • domain。僅顯示來自指定域的資源。可以使用萬用字元字元 (*
    ) 來包含多個域。 例如,*
    .com 將顯示來自以 .com 結尾的所有域名的資源。 DevTools 會使用它遇到的所有域填充自動填充下拉選單。
  • has-response-header。顯示包含指定 HTTP 響應標頭的資源。 DevTools 會使用它遇到的所有響應標頭填充自動填充下拉選單。
  • is。使用 is:running 可以查詢 WebSocket 資源。
  • larger-than。顯示大於指定大小的資源(以位元組為單位)。 將值設為 1000 等同於設定為 1k。
  • method。顯示通過指定 HTTP 方法型別檢索的資源。 DevTools 會使用它遇到的所有 HTTP 方法填充下拉選單。
  • mime-type。顯示指定 MIME 型別的資源。DevTools 會使用它遇到的所有 MIME 型別填充下拉選單。
  • mixed-content。顯示所有混合內容資源 (mixed-content:all),或者僅顯示當前顯示的資源 (mixed-content:displayed)。
    scheme。顯示通過未保護 HTTP (scheme:http) 或受保護 HTTPS (scheme:https) 檢索的資源。
  • set-cookie-domain。顯示具有 Set-Cookie 標頭並帶有與指定值匹配的 Domain 屬性的資源。 DevTools 會使用它遇到的所有 Cookie 域填充自動填充下拉選單。
  • set-cookie-name。顯示具有 Set-Cookie 標頭並且名稱與指定值匹配的資源。 DevTools 會使用它遇到的所有 Cookie 名稱填充自動填充下拉選單。
  • set-cookie-value。顯示具有 Set-Cookie 標頭並且值與指定值匹配的資源。 DevTools 會使用它遇到的所有 Cookie 值填充自動填充下拉選單。
  • status-code。僅顯示 HTTP 狀態程式碼與指定程式碼匹配的資源。 DevTools 會使用它遇到的所有狀態程式碼填充自動填充下拉選單。

? 演示:Filter、複製、儲存和清除網路資訊

一個請求生命週期的主要階段包括:

image.png | center | 827x347

  • 重定向

    • 立即開始 startTime。
    • 如果正在發生重定向,redirectStart 也會開始。
    • 如果重定向在本階段末發生,將採集 redirectEnd。
  • 應用快取

    • 如果是應用快取在實現請求,將採集 fetchStart 時間。
  • DNS

    • domainLookupStart 時間在 DNS 請求開始時採集。
    • domainLookupEnd 時間在 DNS 請求結束時採集。
  • TCP

    • connectStart 在初始連線到伺服器時採集。
    • 如果正在使用 TLS 或 SSL,secureConnectionStart 將在握手(確保連線安全)開始時開始。
    • connectEnd 將在到伺服器的連線完成時採集。
  • 請求

    • requestStart 會在對某個資源的請求被髮送到伺服器後立即採集。
  • 響應

    • responseStart 是伺服器初始響應請求的時間。
    • responseEnd 是請求結束並且資料完成檢索的時間。

Timing 標籤可以檢視網路請求完整的耗時資訊:

image.png | center | 500x433.2688588007737

  • Queuing:請求排隊時間,一般排隊是因為請求優先順序低,或者被暫停(在 HTTP 1 上,瀏覽器僅允許每個源擁有六個 TCP 連線)等。
  • Stalled/Blocking:請求等待傳送所用的時間。
  • Proxy Negotiation:與代理伺服器連線協商所用的時間。
  • DNS Lookup:執行 DNS 查詢所用的時間。
  • Initial Connection / Connecting:建立連線所用的時間,包括 TCP 握手/重試和協商 SSL 的時間。
  • SSL:完成 SSL 握手所用的時間。
  • Request Sent / Sending:發出網路請求所用的時間。 通常不到一毫秒。
  • Waiting (TTFB):等待初始響應所用的時間,也稱為至第一位元組的時間。 此時間將捕捉到伺服器往返的延遲時間,以及等待伺服器傳送響應所用的時間。
  • Content Download / Downloading:接收響應資料所用的時間。

通過 Network 皮膚可以發現大量可能的問題,比如:

有很多被停止的條目:
表明正在從單個域檢索太多的資源。在 HTTP 1.0/1.1 連線上,Chrome 會將每個主機強制設定為最多六個 TCP 連線。要解決此問題,需要實現域分片。也就是在應用上設定多個子域,以便提供資源。比如京東的首頁,就有很多的子域名來載入圖片:

image.png | center | 500x750

至第一位元組的時間很長:
又稱:大片綠色,一般是因為:客戶端與伺服器之間的網路條件較差或者伺服器應用的響應慢。如果本地託管後 TTFB 仍然漫長,那麼問題一般出在客戶端與伺服器之間的網路上。

image.png | center | 257x247

達到吞吐量能力:
又稱:大片藍色。一般是返回的報文太大了,首要的解決辦法是減少傳送的位元組數。

image.png | center | 410x243

? 演示:京東首頁 www.jd.com/;使用 DevTools 可以模擬不同的網路條件,解決載入時間問題。

效能皮膚(Performance)

效能皮膚之前叫 Timeline,在 Chrome 57 之後更名為效能皮膚。主要用來記錄和分析應用在執行時的所有活動。

Performance 皮膚包含以下四個窗格:

  1. Controls。開始記錄,停止記錄和配置記錄期間捕獲的資訊。
  2. Overview。 頁面效能的高階彙總。
  3. 火焰圖。 CPU 堆疊追蹤的視覺化。可以在火焰圖上看到一到三條垂直的虛線。藍線代表 DOMContentLoaded 事件。 綠線代表首次繪製的時間。 紅線代表 load 事件。
  4. Details。選擇事件後,此窗格會顯示與該事件有關的更多資訊。 未選擇事件時,此窗格會顯示選定時間範圍的相關資訊。

image.png | center | 827x649

Overview 窗格包含以下三個圖表:

image.png | center | 827x150

  1. FPS。每秒幀數。綠色豎線越高,FPS 越高。 FPS 圖表上的紅色塊表示長時間幀,很可能會出現卡頓。
  2. CPU。 CPU 資源。此面積圖指示消耗 CPU 資源的事件型別。
  3. NET。每條彩色橫槓表示一種資源。橫槓越長,檢索資源所需的時間越長。 每個橫槓的淺色部分表示等待時間(從請求資源到第一個位元組下載完成的時間)。橫槓按照以下方式進行彩色編碼:

    • HTML 檔案為<span data-type="color" style="color:rgb(110, 161, 226)">藍色</span>
    • 指令碼為<span data-type="color" style="color:rgb(239, 196, 87)">黃色</span>
    • 樣式表為<span data-type="color" style="color:rgb(155, 127, 230)">紫色</span>
    • 媒體檔案為<span data-type="color" style="color:rgb(116, 178, 102)">綠色</span>
    • 其他資源為<span data-type="color" style="color:rgb(179, 179, 179)">灰色</span>

一般效能皮膚主要用於優化頁面的載入時間,提高頁面的流暢度,對於使用者量很大的頁面調優非常有用。比如:

  • 通過找出較長的Evaluate Script 事件,通過 JS 分析器獲取究竟呼叫了哪些 JS 函式以及呼叫每個函式需要多長時間的更詳細資訊。
  • 樣式更改開銷較大,在這些更改會影響 DOM 中的多個元素時更是如此。通過檢查大型 Recalculate Style 事件的記錄(以紫色顯示),如果樣式更改需要較長時間,對效能的影響會非常大。
  • “佈局抖動”是指反覆出現強制同步佈局情況。 這種情況會在 JavaScript 從 DOM 反覆地寫入和讀取時出現,將會強制瀏覽器反覆重新計算佈局。通過觀察紅色豎線標記的 Layout 事件,可以發現佈局方面的問題。
  • 繪製是填充畫素的過程。這經常是渲染流程開銷最大的部分。 在任何情況下注意到頁面出現卡頓現象,很有可能存在繪製問題。

? 演示:快速確定繪製瓶頸,Paint flashing(在Rendering皮膚中),開啟此選項後,每次發生繪製時,Chrome 將讓螢幕閃爍綠色。www.jd.com/

記憶體皮膚(Memory)

記憶體皮膚之前叫 Profile,在 Chrome 57 之後更名為記憶體皮膚。主要用於查詢影響頁面效能的記憶體問題,包括記憶體洩漏、記憶體膨脹和頻繁的垃圾回收。

使用者一般會通過以下方式察覺到有記憶體問題:

  • 頁面的效能隨著時間的延長越來越差。 這可能是記憶體洩漏的症狀。 記憶體洩漏是指,頁面中的錯誤導致頁面隨著時間的延長使用的記憶體越來越多。
  • 頁面的效能一直很糟糕。 這可能是記憶體膨脹的症狀。 記憶體膨脹是指,頁面為達到最佳速度而使用的記憶體比本應使用的記憶體多。
  • 頁面出現延遲或者經常暫停。 這可能是頻繁垃圾回收的症狀。 垃圾回收是指瀏覽器收回記憶體。 瀏覽器決定何時進行垃圾回收。 回收期間,所有指令碼執行都將暫停。因此,如果瀏覽器經常進行垃圾回收,指令碼執行就會被頻繁暫停。

記憶體洩漏很容易確定。如果網站使用的記憶體越來越多,則說明發生記憶體洩漏。記憶體膨脹比較難以界定,一般會考慮網站經常訪問的裝置的配置,說到這裡,插播一下RAIL模型。

使用 RAIL 模型評估效能

RAIL 是一種以使用者為中心的效能模型。每個網路應用均具有與其生命週期有關的四個不同方面,且這些方面以不同的方式影響著效能:

image.png | center | 827x300

讓使用者成為效能工作的中心。使用者花在網站上的大多數時間不是等待載入,而是在使用時等待響應。

延遲與使用者反應:

0 - 16 毫秒使用者可以感知每秒渲染 60 幀的平滑動畫轉場。也就是每幀 16 毫秒
0 - 100 毫秒在此時間視窗內響應使用者操作,他們會覺得可以立即獲得結果。時間再長,操作與反應之間的連線就會中斷。
100 - 300 毫秒使用者會遇到輕微可覺察的延遲。
300 - 1000 毫秒對於網路上的大多數使用者,這個時間段代表任務還在繼續,是合理的延遲。
1000+ 毫秒超過 1 秒,使用者的注意力將離開他們正在執行的任務。
10,000+ 毫秒使用者感到失望,可能會放棄任務;之後他們或許不會再回來。

響應:儘量在 100 毫秒以內響應,對於需要超過 500 毫秒才能完成的操作,要始終提供反饋。

動畫:儘量在 10 毫秒內生成一幀,因為瀏覽器需要花費時間將新幀繪製到螢幕上,所以只有 10 毫秒來執行程式碼。

空閒:最大程度增加空閒時間,利用空閒時間完成推遲的工作。例如,儘可能減少預載入資料,以便應用快速載入,並利用空閒時間載入剩餘資料。

載入:儘量在 1000 毫秒以內呈現內容。

使用 Chrome 工作管理員實時監視記憶體使用,開啟工作管理員,右鍵點選工作管理員的表格標題並啟用 JavaScript memory。

記憶體可以表示為一個由多個互連的點組成的圖表:

image.png | center | 538x339

物件可通過以下兩種方式佔用記憶體:

  • 直接通過物件自身佔用。
  • 通過保持對其他物件的引用隱式佔用,這種方式可以阻止這些物件被垃圾回收器(GC)自動處置。

堆分析器中:

  • Shallow Size(淺層大小),這是物件自身佔用記憶體的大小。
  • Retained Size(保留大小),這是將物件本身連同其相關物件一起刪除後釋放的記憶體大小。

image.png | center | 775x257

記憶體圖從根開始,根可以是瀏覽器的 window 物件或 Node.js 模組的 Global 物件。距離(Distance)欄位,表示與 GC 根之間的距離。

image.png | center | 478x295

任何無法從根到達的物件都會被 GC 回收。

? 演示:按函式調查記憶體分配 Allocation sampling

應用皮膚(Application)

應用皮膚用來檢查載入的所有資源,包括IndexedDB與Web SQL資料庫,本地和會話儲存,cookie,應用程式快取,影象,字型和樣式表。在持久化儲存已經聊過。

? 演示:檢視和編輯本地儲存。

安全皮膚(Security)

安全皮膚主要是用來檢視頁面的整體安全性。

? 演示:

非安全頁面會通過訊息 This page is not secure. 提示

比較:www.google.com/

其他皮膚

? 演示:Audit 基於 Lighthouse,可以用於分析頁面效能。

Chrome 的高效能網路(High Performance Networking)

Chrome 從2008年推出以來,現在已經在全世界瀏覽器市場中佔了第一的份額,而且不斷的在增長。

image.png | center | 827x136

驅動 Chrome 瀏覽器發展的主要是這幾個原則:

  • Speed: 做最快的瀏覽器。
  • Security: 給使用者提供最安全的上網環境。
  • Stability: 提供一個健壯且穩定的Web應用平臺。
  • Simplicity: 提供簡潔的使用者體驗。

這裡所說的高效能網路,就是遵循了第一個原則:Speed。

之前說過一個網路請求的生命週期中間有很多步驟:

image.png | center | 635x348

這中間DNS查詢、TCP三次握手、SSL握手等等,都會耗費一定的時間,對於響應比較快的請求,可能80%以上的開銷都在網路上。

Chrome 的多程式架構為瀏覽器的網路請求處理帶來了重要意義,它目前支援四種不同的執行模式:

  • Process-per-site-instance:就是開啟一個網站,然後從這個網站開的每一個Tab屬於一個程式。優點:隔離性很強;缺點:記憶體開銷大,實現複雜。
  • Process-per-site:同域名的網站Tab放在一個程式。
  • Process-per-tab:一個Tab一個程式。
  • Single process:傳統模式,只有一個程式。

預設情況下,桌面的 Chrome 瀏覽器使用 process-per-site 模式, 將不同的網站頁面隔離起來, 相同網站的頁面組織在一起。

Chrome Predictor 預測功能優化:

Chrome會隨著使用變得更快。Predictor 會觀察和學習當前網路活動方式,提前預估使用者下一步的操作。比如:

  • 使用者將滑鼠停留在一個連結上,就預示著一個使用者的偏好以及下一步的瀏覽行為。這時 Chrome 就可以提前進行 DNS Lookup 及 TCP 握手。使用者的點選操作平均需要將近 200ms,在這個時間就可能處理完 DNS 和 TCP 相關的操作, 也就是省去幾百毫秒的延遲時間。
  • 當在位址列觸發高可能性選項時,就同樣會觸發一個 DNS lookup 和 TCP 預連線(pre-connect),甚至在一個不可見的頁籤中進行預渲染(pre-render)。
  • 我們每個人都一串天天會訪問的網站, Chrome 會研究在這些頁面上的子資源, 並且嘗試進行預解析(pre-resolve), 甚至可能會進行預載入(pre-fetch)以優化瀏覽體驗。

Chrome採用了四種核心優化技術:

  • DNS pre-resolve:DNS 預解析,提前解析主機地址,以減少 DNS 延遲。
  • TCP pre-connect:TCP 預連線,提前連線到目標伺服器,以減少 TCP 握手延遲。
  • Resource prefetching:資源預載入,提前載入頁面的核心資源,以加快頁面顯示。
  • Page prerendering:頁面預渲染,提前獲取整個頁面和相關子資源。

? 演示:chrome://predictors/

Chrome會維護使用者輸入的字首的歷史記錄,建議的操作以及每個字首的命中率。比如我平時輸入了 appl,那麼 100% 是要訪問蘋果官網。

TL;DR

這次主要聊了前端大概的演變,瀏覽器的一些基礎,之後有時間會聊聊協議、安全、框架、實踐、跨棧之類的,大家辛苦!


相關文章