這是探索 JavaScript 及其內建組件系列文章的第 12 篇。在認識和描述這些核心元素的過程當中,咱們也會分享咱們在構建 SessionStack 時所遵循的一些經驗規則。SessionStack 是一個輕量級 JavaScript 應用,它協助用戶實時查看和復現他們的 Web 應用缺陷,所以其自身不只須要足夠健壯還要有不俗的性能表現。javascript
若是你錯過了前面的文章,你能夠在下面找到它們:前端
正如咱們在前一篇關於渲染引擎的文章中所說的,咱們相信,優秀的 JavaScript 開發者和傑出的 JavaScript 開發者之間的區別在於後者不只懂得如何使用這門語言,還可以理解它的內在以及周遭環境。java
49 年前,一個叫作 ARPAnet 的東西被創造了出來。它是一個早期的數據包交換網絡,也是第一個實踐 TCP/IP 套件的網絡。該網絡在加州大學和斯坦福研究中心之間搭建了一個鏈接。20年後,Tim Berners-Lee 發佈了一個名爲『Mesh』的提案,也就是後來人們所說的萬維網。在這 49 年裏,互聯網走過了漫長的道路,從兩臺計算機交換數據包開始,到現在擁有超過 7500 萬臺服務器,38 億名用戶和 13 億個網站。android
在這邊文章中,咱們將嘗試分析現代瀏覽器使用了哪些技術來自動地提升性能(有些你甚至並不知道)。咱們將尤爲關注瀏覽器的網絡層。在最後,咱們將會提供一些建議,關於如何使得瀏覽器可以更好地提高你的 Web 應用的性能。ios
爲了可以快速、高效而且安全地展現 Web 應用/網站,現代的瀏覽器都是通過特別設計的。數百個組件運行在不一樣的層上,從進程管理和安全沙盒到 GPU 流水線,音頻和視頻等等,Web瀏覽器看起來更像是一個操做系統,而不只僅是一個軟件應用程序。git
瀏覽器的總體性能取決於許多大型組件:解析、佈局、樣式計算、JavaScript 和 WebAssembly 執行、渲染,固然還有網絡棧。github
工程師常常認爲網絡棧是一個瓶頸。一般來講,確實如此,由於在執行接下來的步驟以前,先得從互聯網上獲取到全部的資源。爲了提升網絡層的效率,它不只須要扮演簡單的套接字管理員的角色。它呈現給咱們的只是一種很是簡單的資源獲取機制,但它其實是一個擁有本身的優化標準,API 和服務的完整平臺。web
做爲 Web 開發人員,咱們沒必要操心個別的 TCP 或 UDP 數據包、請求格式化、緩存和此過程當中的其餘全部事情。因此複雜的事務都由瀏覽器處理,所以咱們能夠專一於咱們正在開發的應用程序。可是,瞭解底層究竟發生了什麼,能夠幫助咱們建立更快、更安全的應用程序。chrome
實質上,當用戶開始與瀏覽器交互時發生瞭如下事務:編程
W3C 的導航時序規範提供了瀏覽器 API,它可以提供瀏覽器中每一個請求的生命週期背後的時間和性能數據。讓咱們來看看這些組件,由於它們在提供最佳用戶體驗方面起着相當重要的做用:
這個網絡通訊的過程是很是複雜的,有不少不一樣的層可能成爲瓶頸。這就是爲何瀏覽器努力經過使用各類技術來提升性能的緣由,以便整個網絡通訊的影響最小。
讓咱們先從一些術語開始:
JavaScript 和 WebAssembly 不容許咱們管理網絡套接字的生命週期,這是一件好事!這不只可使咱們免去不少麻煩,並且還可讓瀏覽器自動去進行大量的性能優化,其中一些包括套接字重用,請求優先級和後期綁定,協議協商,強制鏈接限制等等。
實際上,現代瀏覽器更進了一步,把請求管理週期與套接字管理分立了開來。套接字按池組織,按源分組,每一個池強制實施本身的鏈接限制和安全約束。待處理的請求會先排隊,再按優先級處理,而後綁定到池中的單個套接字上。除非服務器有意關閉鏈接,不然能夠在多個請求中自動重用相同的套接字!
因爲開闢新的 TCP 鏈接須要額外的成本,所以鏈接的重用具備很大的性能優點。默認狀況下,瀏覽器使用所謂的「keepalive」機制,這能夠節省出在已有請求發生後再打開新鏈接到服務器的時間。打開一個新的 TCP 鏈接的平均時間是:
23ms
120ms
225ms
這種架構爲其餘一些優化提供了可能。這些請求能夠根據其優先級以不一樣的順序執行。瀏覽器能夠優化全部套接字的帶寬分配,或者在預期請求時先打開套接字。
正如我以前提到的,這一切都是由瀏覽器自行管理的,並不須要咱們作任何工做。但這並不必定意味着咱們什麼都作不了。選擇合適的網絡通訊模式,傳輸類型和頻率,恰當地選擇協議以及調整/優化服務器架構能夠在提升應用程序的總體性能方面發揮重要做用。
有些瀏覽器甚至更進一步。例如,Chrome 能夠學習用戶的操做習慣來使本身變得更快。它根據用戶訪問的網站和典型的瀏覽模式進行學習,以便在用戶作任何事情以前預測可能的用戶行爲並採起行動。最簡單的例子是當用戶在連接上懸停時,Chrome 會預先渲染頁面。若是您有興趣瞭解有關 Chrome 優化的更多信息,能夠查看高性能瀏覽器網絡(High-Performance Browser Networking)一書中的本章節 www.igvita.com/posa/high-p…。
容許瀏覽器管理單個套接字具備另外一個很是重要的目的:經過這種方式,瀏覽器能夠對不可信的應用程序資源強制執行一致的安全和策略約束。例如,瀏覽器不容許經過 API 直接訪問原始網絡套接字,由於這可使任何惡意應用程序與任何主機進行任意鏈接。瀏覽器還強制性地限制鏈接數,以保護服務器以及客戶端免受資源耗盡的問題。
瀏覽器格式化全部傳出請求,以強制實行風格一致且格式良好的協議語義來保護服務器。一樣,響應解碼自動完成,以保護用戶免受惡意服務器的侵害。
傳輸層安全協定(TLS)是一種在計算機網絡上提供安全通訊保障的加密協議。它在許多應用程序中普遍使用,其中之一是網頁瀏覽。網站可使用 TLS 來保護其服務器和 Web 瀏覽器之間的全部通訊。
完整的 TLS 握手包含如下幾步:
任何一步校驗失敗,用戶都將會收到警告。例如,服務器正在使用自簽名證書。
若是兩個頁面的協議、端口和主機名都相同的話,那麼這兩個頁面同源。
如下是一些可能嵌入跨源資源的一些例子:
<script src=」…」></script>
引用 JavaScript 資源。語法錯誤的錯誤消息僅適用於同源腳本<link rel=」stylesheet」 href=」…」>
引用 CSS 資源。因爲 CSS 的寬鬆語法規則,跨源 CSS 須要正確的 Content-Type 標頭。不一樣瀏覽器可能有不一樣的限制。<img>
引用圖像資源。<video>
和 <audio>
引用多媒體資源。<object>
、<embed>
和 <applet>
引用插件資源。<frame>
和 <iframe>
引用的資源。網站可使用 X-Frame-Options 頭部標識來阻止這種形式的跨源交互。以上列表遠非完整;其目地是爲了突出『最小特權』原則。 瀏覽器只公開應用程序代碼必須的 API 和資源:應用程序提供數據和 URL,瀏覽器格式化請求並處理每一個鏈接的完整生命週期。
值得注意的是,『同源策略』並不是是個單一的概念。相反,有一組相關機制來強制性地限制 DOM 訪問,Cookie 和會話狀態管理,網絡以及瀏覽器的其餘組件。
最好和最快的請求是未發出的請求。在分派請求以前,瀏覽器會自動檢查其資源緩存,執行必要的驗證檢查,並在知足指定條件時返回資源的本地副本。若是本地資源在緩存中不可用,則會發出網絡請求,而且響應會被自動放入緩存中以供後續訪問(若是容許)。
管理高效和優化的資源緩存是很困難的。值得慶幸的是,瀏覽器替咱們完成了全部複雜的事務,咱們只須要確保咱們的服務器返回適當的緩存指令;要了解更多信息,請參見客戶端上的緩存資源(Cache Resources on the Client)。您確實有爲網頁上的全部資源都提供了 Cache-Control,ETag 和 Last-Modified 響應頭部字段,對吧?
最後,瀏覽器常常被忽視但相當重要的功能是提供身份驗證,會話和 cookie 管理。瀏覽器爲每一個源維護單獨的「Cookie jars」,提供必要的應用程序和服務器 API 來讀取和寫入新的 Cookie,會話和身份驗證數據,並自動附加上和處理相應的 HTTP 頭以代替咱們自動執行整個過程。
用一個簡單但有說明性的例子來講明將會話狀態管理推放到瀏覽器端的便利之處:同一個通過身份驗證的會話能夠在多個選項卡或瀏覽器窗口之間共享,反之亦然;單個選項卡中的註銷操做將使全部其餘打開的窗口中打開的會話失效。
研究完了網絡服務,終於到達了應用程序 API 和協議這一步。正如咱們所看到的,較低層提供了一系列關鍵服務:套接字和鏈接管理、請求和響應處理、各類安全策略的執行、緩存等等。每次咱們啓動一個 HTTP、一個XMLHttpRequest 或是一個長期的 Server-Sent Event 或 WebSocket 會話,或是打開一個 WebRTC 鏈接,咱們都在與這些底層服務的一部分或所有進行交互。
沒有單一的最佳協議或 API。每一個不平凡的應用程序都須要根據各類需求混合使用不一樣的傳輸:與瀏覽器緩存的交互、協議開銷、消息延遲、可靠性、數據傳輸類型等等。某些協議可能提供低延遲傳輸(例如 Server-Sent Events,WebSocket),但可能不符合其餘關鍵條件,例如在全部狀況下都可以利用瀏覽器緩存或支持高效二進制傳輸。
性能和安全性二者都是 SessionStack 中的一等公民。咱們沒法妥協的緣由在於,一旦 SessionStack 集成到您的 Web 應用程序中,它就會開始監視從 DOM 更改、用戶交互到網絡請求,未處理的異常和調試消息的全部內容。全部數據都會實時傳輸到咱們的服務器上,這樣您就可以以視頻的形式重現用戶遇到的一切狀況。 而這一切都是以最短的延遲進行的,不會對應用程序形成任何額外的性能開銷。
這就是爲什麼咱們努力實踐以上全部提示,以及咱們將在將來發布的內容中討論的更多內容。
若是你想試一試 SessionStack,這有一個免費的計劃。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。