【譯】使用 Script-Streaming 提升頁面加載性能

script-streaming 是什么?

加載 JavaScript 算是 web 性能最嚴(yán)重的瓶頸之一,尤其在低端 CPU 上情況更糟糕。加載 JavaScript 的性能損耗不僅包括從服務(wù)器上下載數(shù)據(jù)的網(wǎng)絡(luò)時(shí)間,也包括文件解壓、解析、編譯,以及執(zhí)行 JavaScript 的時(shí)間。為了更好的用戶體驗(yàn),web 頁面大量的 JavaScript 代碼數(shù)量持續(xù)地增長,頁面加載變得越來越慢。瀏覽器社區(qū)一直在開發(fā)很多優(yōu)化措施來提升 JavaScript 加載速度,比如將解析 JavaScript 文件和下載過程并行化(在此之前,瀏覽器會(huì)等待 JavaScript 文件完全下載后才會(huì)在渲染主線程上進(jìn)行解析)。這項(xiàng)優(yōu)化措施就是 script-streaming,它在 Chrome v41 上被引入。Google 聲稱 script-streaming 能夠?qū)㈨撁婕虞d速度提升 10%,因?yàn)榇笮?JavaScript 文件會(huì)邊下載邊解析,這可以減少數(shù)百毫秒的頁面加載時(shí)間。

Script-streaming 是為加速 JavaScript 解析而做的一項(xiàng)巨大的優(yōu)化。然而,Chrome 針對 JavaScript 文件啟用 script-streaming 還有一些限制。

  • 首先,下載的 JavaScript 文件大小至少 30KB。這個(gè)尺寸限制確保了只有大型 JS 文件能夠通過 script-streaming 解析,因?yàn)橄啾扔谳^小的 JavaScript 文件,并行下載和解析大型 JavaScript 文件的收益最大。

  • 其次,目前 Chrome 在 script-streaming 的實(shí)現(xiàn)上,同一時(shí)刻 script-streaming 只能應(yīng)用到一個(gè) JavaScript 文件上。這是由于 Chrome 對于 script-streaming 只使用了單線程。既然這個(gè)線程忙于解析某個(gè) JavaScript 文件,那么其他 JavaScript 文件就必須在主線程下載完成后,才能進(jìn)行解析。

web 開發(fā)者如何利用 script-streaming ?

script-streaming 加速了 JavaScript 的解析。作為一個(gè) web 開發(fā)者,你不必為了在頁面上啟用 script-streaming 做任何事情。然而,script-streaming 還是有一些限制的,這些限制只存在于 Chrome,它們是由于 Chrome 的實(shí)現(xiàn)造成的。具體來說,當(dāng)大型 JavaScript 文件下載完成,script-streaming 線程不保證一定可用。同樣地,頁面并行下載多個(gè)大型 JavaScript 文件,只有一個(gè)文件能夠通過 script-streaming 解析。并且,某些情況下,script-streaming 可能解析較小的腳本文件,而較大的腳本只能等待 script-streaming 線程可用,或者在完成下載后,由主線程進(jìn)行解析。

開發(fā)者可以使用 performance 開發(fā)者工具來研究 script-streaming 是否被用于解析大型 JavaScript 文件,因?yàn)檫@項(xiàng)技術(shù)可以顯著提升頁面性能。下圖是 www.akamai.com 在 performance 面板上的一個(gè)截圖,腳本就是被紅框里的 ScriptStreamer 線程解析的。

[圖片上傳失敗...(image-229024-1538213191690)]

提升解析速度的兩種方法

我做了一些研究,為了啟用 script-streaming,可以解析較小的 JavaScript 文件(仍然大于 30KB),這樣在解析相對較大的 JavaScript 文件時(shí),保持線程是可用的。理論上,可以在大型 JavaScript 文件上發(fā)送一個(gè) HTTP 響應(yīng)頭,告訴瀏覽器在具有這種響應(yīng)頭的文件上應(yīng)用 script-streaming。然而,這個(gè)方法要求主流瀏覽器作出調(diào)整,并且能讓 script-streaming 利用多線程,而不僅僅是單線程。值得注意的是,目前 使用多個(gè) script-streaming 線程在 Chrome 團(tuán)隊(duì)內(nèi)部依然是 TODO 狀態(tài)。

一個(gè)比較實(shí)用的,執(zhí)行起來簡單得多,并且不需要瀏覽器改變的技巧,是重新排序 HTML 中那些加載靜態(tài)資源 URL 的 <script> 標(biāo)簽的位置,以讓大的 JavaScript 文件在較小(仍然大于 30KB)文件之前下載。當(dāng) script-streaming 可用時(shí),此方法會(huì)強(qiáng)制解析大型 JavaScript 文件。重新排序 <script> 標(biāo)簽在 HTML 中的位置,可能存在潛在風(fēng)險(xiǎn)。因?yàn)闉榱吮3猪撁娴墓δ芎?UI,一些 JavaScript 必須按順序執(zhí)行。因此,在重新排序時(shí)必須要謹(jǐn)慎。重新排序那些帶上=有 async 或者 defer 屬性的 <script> 標(biāo)簽會(huì)保險(xiǎn)一些,因?yàn)檫@些腳本執(zhí)行并不依賴于執(zhí)行順序。由于腳本重排序伴隨著種種限制,這項(xiàng)實(shí)驗(yàn)性的方法將只在指定的網(wǎng)站上生效。除了腳本重排序之外,我加進(jìn)來的另一個(gè)方法是,將多個(gè)大型 JavaScript 文件并行下載,讓它們競爭 script-streaming 線程。我將所有這樣的 JavaScript 文件串聯(lián)起來,目的是讓他們都可以實(shí)現(xiàn)邊下載邊解析。

實(shí)驗(yàn)結(jié)果

我做了一些實(shí)驗(yàn),去衡量上述兩個(gè)方法在多個(gè)設(shè)備上的頁面加載時(shí)間,包括 MacBook Pro,一個(gè)低端移動(dòng)設(shè)備(Motorola Moto E),和一個(gè)高端移動(dòng)設(shè)備(Motorola Moto G)。性能數(shù)據(jù)通過一個(gè)私有網(wǎng)頁測試實(shí)例.收集。在兩個(gè)手動(dòng)修改的網(wǎng)站(“Page A” 和 “Page B”,詳情見下表)集合上,觀察到在多個(gè)移動(dòng)設(shè)備和 MacBook Pro 上,對于中等規(guī)模的頁面有多達(dá) 6.2% 的頁面加載時(shí)間提升。這些性能提升要?dú)w功于 JavaScript 解析和下載的并行化。

Page \資源數(shù) 頁面大小 #JavaScript 資源數(shù) ** JavaScript 總大小**
A 41 2.7 MB 12 1.3 MB
B 95 2.2 MB 19 1.1 MB

MacBook Pro 上的性能

圖 1 和圖 2 展示了在一臺(tái) MacBook Pro 上,兩個(gè)測試頁面加載時(shí)間的 CDF 分布。頁面 A 上,重新排序 script 標(biāo)簽在 HTML 中的位置的頁面加載時(shí)間減少了 6.2%。頁面 B 上,加載重新排序的 scrip 標(biāo)簽的頁面加載時(shí)間減少了 4.5%。
[圖片上傳失敗...(image-cc044e-1538213191690)]

Motorola Moto E 上的性能

正如下圖所示,重排序 script 標(biāo)簽的頁面 A 的加載時(shí)間減少了 4.3%。

頁面 B(沒有示例圖)上沒有出現(xiàn)更快的加載速度,這可能是因?yàn)樵?Moto E 設(shè)備上,當(dāng)移動(dòng)版頁面 A 加載時(shí), script-streaming 線程被占用了。
[圖片上傳失敗...(image-dccbb4-1538213191690)]

Motorola Moto G 上的性能

如下圖所示,重排序 script 標(biāo)簽的頁面 A 的加載時(shí)間減少了 3.5%。

頁面 B 上,中等規(guī)模頁面的加載時(shí)間減少了 1.9%。
[圖片上傳失敗...(image-bf44d5-1538213191690)]

總結(jié)

本文描述的實(shí)驗(yàn)性工作舉例說明了相比默認(rèn)的解析,通過 script-streaming 解析較大 JavaScript 文件帶來的好處。實(shí)驗(yàn)包含重排序 HTML 中的 <script> 標(biāo)簽,以及串聯(lián)多個(gè)大型 JavaScript 文件,讓它們并行下載,以允許相對較大的文件能夠通過 script-streaming 解析。實(shí)驗(yàn)結(jié)果顯示,在 MacBook Pro 和兩個(gè)低端和高端的移動(dòng)設(shè)備上,對于中等大小的頁面,加載速度有多達(dá) 6% 的提升。


原文作者: Utkarsh Goel

譯者: 熊賢仁

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,104評(píng)論 2 59
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 30,282評(píng)論 8 265
  • 56【反思】月度檢視是一個(gè)好習(xí)慣 如何過一天,就是如何過一生。 沒有反思的人生不值得過。 月度檢視就是要堅(jiān)持紀(jì)錄,...
    依盈閱讀 79評(píng)論 0 0
  • 昨晚彭彭幫愛人涂指甲油,我泡腳看著她們。想起之前幫宛芯畫眉,啊哈哈。 而我在泡腳的同時(shí)也敗了100多,悅詩風(fēng)吟的眉...
    大大大未至閱讀 139評(píng)論 0 0

友情鏈接更多精彩內(nèi)容