[譯] Javascript開銷(Cost)

原文連接:https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99ejavascript

當咱們創建的網站愈來愈多依賴Javascript時,咱們有時候會爲了一些咱們不容易看到的地方付出代價。在這邊文章中,我會講述一些規範,若是你想讓你的網站在移動設備上更快加載和響應的話,這些規範可能會對你有幫助。html

tl;dr: less code = less parse/compile + less transfer + less to decompress前端

tl;dr是too long; don't read的縮寫java

網絡

當大多數開發者想到Javascript的開銷時,可能會聯想到下載和執行開銷。傳送的數據量越大,那用戶鏈接的速度就越緩慢。webpack

1_U00XcnhqoczTuJ8NH8UhOw.png

即便在一些大國家,若是用戶的有效網絡不是3G, 4G 或者WiFi的話(用戶可能在咖啡廳用着wifi,可是實際網速是2G),那麼這就會成爲一個問題。git

你能夠經過如下幾種方式來減小網絡傳輸的開銷:github

1_8Spf9To8dzTG3Xy9s57oVA.png

解析/編譯

一旦腳本下載完成了以後,JS最大的開銷之一就是JS引擎的解析/編譯代碼。在Chrome開發者工具裏的「性能」模塊,解析和編譯代碼用黃色標識.web

1__4gNDmBlXxOF2-KmsOrKkw.png

經過Bottom-Up/Call Tree(調用樹),能夠看實際的解析/編譯用時:npm

1_GdrVt_BTTzzBOIoyZZsQZQ.png

可是,爲何這個很重要呢?小程序

1_Dirw7RdQj9Dktc-Ny6-xbA.png

花費大量時間在解析/編譯代碼上會延遲用戶與網站的交互,破壞用戶體驗。在網站呈現以前,JS量越大,花在解析/編譯上的時間就越長。

1_6Y665hpxfWNMu2EXu3VGlw.png

對於大小相同的JS和圖片或者網頁字體,JS須要瀏覽器花費的時間最多— Tom Dale

與Javascript相比,處理相同大小的圖片所須要的開銷明顯小不少。

1_PRVzNizF9jQ_QADF5lQHpA.png

當咱們討論解析和編譯的速度之慢時,上下文是很重要的。咱們的討論是基於平均水平的移動設備。平均水平的用戶使用的移動設備多是CPU/GPU很慢的、沒有L2/L3緩存的或者甚至內存頗有限的。

網絡和設備不老是匹配的。一個用戶可能有很好的網絡條件,可是隻有一部爛手機。相反,一個用戶可能有一部神機,卻碰上了龜速網絡 — Kristofer Baxter, LinkedIn

JavaScript Start-up Performance文中, 我提到了分別在低端和高端機型中1MB原始JS代碼的解析時間. 它們之間的差距達到了2-5倍.

1_8BQ3bCYu1AVvJWPR1x8Yig.png

那實際的網站如何呢,好比CNN.com?

在高端機iPhone 8上,解析/編譯JS代碼只需大約4s,而在平均水平的手機Moto G4上卻要花上將近13s。這很明顯得影響了用戶可以多快看到界面。

1_7ysArXJ4nN0rQEMT9yZ_Sg.png

這就要求咱們要更加註重一些平均水平的設備的測試,而不只僅是本身口袋裏的高端機。上下文是很重要的:必定要針對你的用戶的設備和網絡進行優化。

1_6oEpMEi_pjRNjmtN9i2TCA.png

能夠經過 mobile device classes 來看看真實用戶的分析狀況。

咱們真的是傳輸了太多的JS代碼嗎? 呃。。有可能 :)

使用HTTP Archive (top ~500K sites)來分析JS在移動設備上的使用狀況JavaScript on mobile, 咱們就能發現50%左右的網站須要14s以上才能真正讓用戶用上。這些網站光花在解析/編譯JS上的時間就多達4s.

1_sVgunAoet0i5FWEI9NSyMg.png

介於以上這些狀況,怪不得用戶在尚未看到頁面以前就離開了。咱們固然能夠在這點上作得更好。

刪除一些非必要JS代碼能有效減小轉換時間、CPU的解析/編譯時間以及內存佔用。一樣也能是用戶更快得與網站交互。

執行時間

固然,編譯和解析只是JS開銷的一部分。執行JS代碼也是主線程上必需要作的,若是執行時間冗長,也會直接影響用戶體驗。

1_ec0wEKKVl7iQidBks3oDKg.png

一旦腳本執行時間超過50ms,後果不堪設想 — Alex Russell

爲了減小執行時間,你能夠將JS代碼分離成一塊塊的,以避免阻塞主線程。

設計模式

有時候一些設計模式可以幫助你,好比基於路由的代碼分塊 (route-based chunking) 或者PRPL.

以下圖所示,PRPL就是一個利用代碼分離和緩存方式來優化交互體驗的模式:

1_VgdNbnl08gcetpqE1t9P9w.png

讓咱們來看看這個影響.

咱們使用V8的 Runtime Call Stats 分析了一些主流網站以及PWA的加載時間。能夠看到,解析時間在整個加載時間中佔了可觀的部分:

1_9BMRW5i_bS4By_JSESXX8A.png

Wego,是使用了PRPL的一個站點,讓每一個路由都保持不多的解析時間,使得用戶能更快得與網站交互。上圖中的不少網站也是採用了代碼分離和性能預算 (performance budget) 來嘗試下降JS開銷。

其它開銷

JS也會在其它方面影響頁面性能:

  • 內存。頁面可能會由於垃圾回收而致使頻繁的閃爍或暫停。當瀏覽器回收內存的時候,JS執行就會暫停。這就致使了當瀏覽器頻繁回收垃圾時,JS執行的暫停頻率就會比咱們想象中的更多。避免內存泄漏和頻繁的垃圾回收可以是頁面更穩定。

  • 在運行時,若是JS運行時間過長就會阻塞主進程,致使頁面沒法交互。把這些任務分紅一小塊一小塊 (能夠採用 requestAnimationFrame() 或者 requestIdleCallback() 或者 scheduling) 可以最小化其帶來的影響。

漸進式 Bootstrapping

爲了讓網站更快呈如今用戶面前,許多網站會使用服務器端渲染來實現,而後在頁面返回後經過綁定事件來「升級」它。

小心 -- 這種方式也有它的開銷。一方面傳輸回來的HTML比較大,另外一方面用戶必須等到JS處理完畢才能真正與頁面進行交互。

漸進式 Bootstrapping 多是一種更好的方法。先發送一部分功能性頁面(只是當前路由須要的HTML/JS/CSS)回來。當更多的資源傳輸回來時,頁面就會進行懶加載而且解鎖更多的功能。

1_zY03Y5nVEY21FXA63Qe8PA.png

加載當前頁面的代碼實在是很是好的方法。PRPL和漸進式 Bootstrapping 就是能幫助實現這點的模式。

結論

在網絡不佳的狀況下,傳輸數據的大小是相當重要的。對於CPU不給力的設備,解析時間是很重要的。

參考 Alex Russell 的 「Can You Afford It?: Real-world Web Performance Budgets」。

1_U8PJVNrA_tYADQ6_S4HUYw.png

若是你正在搭建一個基於移動設備的站點,儘可能在典型的設備上開發。減小JS解析/編譯時間,採用Performance Budget讓團隊成員都能檢測JS開銷。

硬廣

這是本人的前端技術小程序,基本上全部的文章都會同步更新在小程序中。歡迎你們來湊熱鬧。

image
image
相關文章
相關標籤/搜索