974
汽車大全
前端性能優化(三)——傳統 JavaScript 優化的誤區
注:本文是純技術探討文,無圖無笑點,希望您喜歡
一.前言
軟件行業極其缺乏前端人才這是圈內的共識了,某種程度上講,同等水平前端的工資都要比後端高上不少,而圈內的另一項共識則是——***網頁是公司的臉麵!***
幾年前,穀歌的一項統計表明,如果亞馬遜頁麵加載每慢 100ms,將影響他們 1% 的收入;如果穀歌頁麵加載慢 500ms,流量將銳減 20%,這個數據現在必將更加恐怖!
在前端高性能優化(一)、(二)中,筆者介紹了一些關於前端優化的技術,這些技術都依賴於前人的辛苦努力,但我們仍要明白的是,前端的情況十分複雜,優化前端性能是必須**因地製宜、因時製宜。**
在本篇文章中,主要介紹的就是在一些條件下,傳統優化 JavaScript 的技術並不像我們認為的那樣適用。
二.JavaScript 模塊化誤區
加快 JavaScript 加載和執行的速度,一直是前端優化的一個熱點。因此我們先來說下 JavaScript 模塊化技術的相關知識,希望通過實踐來體現模塊化技術在使用時的注意事項,避免濫用。
為什麼會有模塊化技術?
長久以來,編寫 JavaScript 一直以文件為單位,一般一個類型的 JavaScript 功能代碼會被放在同一個文件裏。在一個頁麵裏,引用的文件一般是寫死的,也就是不管頁麵用不用,隻要你引入了這個文件,這個文件就會被加載。
舉個例子,我們開發了一個內容複雜、功能強大的頁麵,JavaScript 文件大到 500K,當頁麵費勁的把這 500K 加載下來,然而用戶真正隻使用了這 500K 裏極少的一部分功能,但我們又不得不把這 500K 加載下來,因為不同的用戶使用的功能點可能不一樣,我們必須滿足所有需求。
而模塊化技術提出 按需加載,也就是當用戶觸發該功能的時候,那個功能才真正的被加載。好比 500K 被拆成了 50 個模塊,每個模塊 10K,當用戶觸發一個功能時,加載 10K,再觸發再加載,以這樣懶加載的方式來加載模塊,可以很大的提高響應速度。這樣,管理模塊懶加載的技術也隨之誕生。
模塊化技術並非到處靠譜!!
之前筆者在網上搜索到了一個模塊化技術:**SeaJS**。它是一個遵循 CommonJS 規範的 JavaScript 模塊加載框架,可以實現 JavaScript 的模塊化開發及加載機製。與 JQuery 等 JavaScript 框架不同,SeaJS 不會擴展封裝語言特性,而隻是實現 JavaScript 的模塊化及按模塊加載。
SeaJS 的主要目的是令 JavaScript 開發模塊化並可以輕鬆愉悅進行加載,將前端工程師從繁重的 JavaScript 文件及對象依賴處理中解放出來,可以專注於代碼本身的邏輯。說白了就是有 Lazy Load 的特性,用到某模塊時,SeaJS 才會去加載模塊的 JS 文件。我們可以按功能劃分多個模塊,觸發模塊功能時,SeaJS 先加載功能模塊的文件,然後執行相應的功能。
這個 SeaJS 擁有的特性,初看非常吸引人,它可以說是新定義了一種開發和管理 JavaScript 文件的模式。遵循這個模式,你會享受起 JavaScript 的開發。
實踐證明,它也的確可以使 JavaScript 模塊化,根據功能劃分模塊,每個模塊對應一個 JavaScript 文件,當執行到模塊的功能,或者你需要加載模塊時,模塊才會被下載,同時不會造成重複下載。這一切看起來如此的合理,如此的順暢。。。。。
但是在使用後發現了一些 問題:由於當時開發的網站功能相對簡單,JavaScript 文件並不是非常大,過多的模塊,反而會導致總加載的時間變多了。
由於是 Lazy Load 特性,不適合的模塊劃分導致網站出現反應慢的現象,原因是得先加載模塊的文件,才能執行模塊的功能。當網絡情況不好時,該現象表現的更為嚴重!!!
可以說,問題出在了對新技術的不了解上,從而出現了問題,預期是 SeaJS 可以處理 JavaScript 優化的問題,因為它具有避免加載不必要模塊的功能,結果反而南轅北轍。
總結
雖然嚐試出現了問題,但是,收獲也是巨大的,簡單來說就是以下兩點:
1)因地製宜,根據實際需要使用模塊化技術,切勿跟風技術,在自己沒有完全掌握時,謹慎用於產品中。
2)模塊如果是懶加載的,粒度不能太小,也就是模塊不能太小。
根據 大功能來劃分模塊 也是一個不錯的嚐試。
筆者嚐試將所有模塊劃分為 基礎模塊 和 功能模塊 ,基礎模塊包括頁麵頭部,尾部相關的公共部分,功能模塊則根據前後台劃分,前台部分,又根據具體的頁麵來劃分,能合並到一起的,就合並成一個模塊,增加粒度。結果 JavaScript 文件減少,也達到了預期的效果。
從實際體驗來看,對於流量不大的網站來說,沒有必要使用懶加載 JavaScript 的相關技術,因為本身 JavaScript 文件就不是非常大。**因此在網頁加載時,就可以先加載所需要的模塊。避免不必要的延遲。**
三.JavaScript 的位置問題
這一部分,我們來說說 JavaScript 的位置問題對網頁網站性能的影響。
為什麼要考慮位置問題?
其實不管是 CSS 還是 JavaScript,都需要考慮位置的問題,因為 HTML 的渲染和加載順序是從上往下,也就是如果前麵插入了 JavaScript 的引用,那麼必須等到這個 JavaScript 下載完畢才會渲染後續的部分。
因此 JavaScript 的插入位置就成為一個值得考慮的問題,因為不適合的位置可能引起渲染的延遲等,造成不好的用戶體驗。
傳統方案帶來的問題和思考
CSS 放在頭部,JavaScript 放在尾部,這是傳統的經驗,它的好處是可以讓頁麵優先渲染, 從而頁麵可以快速顯示。
但有事實往往沒有我們預想的那麼美好。
有的時候會出現這麼一種情況:當頁麵已經渲染完畢時,我們立刻去使用網站的功能,但很多時候 功能按鈕會沒有反應。原因也很簡單,就是 JavaScript 放在頁麵的尾部,還沒來得及加載。。。。
這就糾結了。。。。
兩種 JavaScript 放置方式,一種放在頭部,一種放在尾部(暫時忽略部分放在頭部,部分放在尾部的方式),一個犧牲了渲染速度,一個犧牲了用戶體驗。所以很多時候 js 的問題我們需要做權衡。
對一般的小型網站來說,用戶體驗問題要遠遠大於頁麵渲染的問題,就比如上文提到的那種功能按鈕不可用的情況。而且,如果 JavaScript 不是很大的話,放在頭部就很好,既不會有太久的頁麵空白,也能讓其優先加載,二者得到了很好的平衡。
因此,很多經驗上的東西並不是絕對的,一定要根據實際的情況,包括功能特點、服務器網絡情況等來綜合考慮。
為此,筆者寫下一個自認為較為合理的位置選擇方案,僅供參考。
從上麵的分類介紹,我們也可以看出,將功能代碼按類型歸類到不同的 JavaScript 文件是多麼的重要,比如應該放頭部和應該放尾部的代碼,最好不要合並在一起,不要等到出問題要優化的時候再去整理和重構,這樣會增加很多不必要的工作量。
這不僅僅是為自己工作負責,也是為後麵要讀你代碼的新人負責。養成好的設計編碼習慣,也是技術積累的一部分。最後再根據 JavaScript 文件的功能類型,來決定是放在頁麵的頭部還是尾部。
四.怎樣確定是不是 JavaScript 的問題?
這個問題在之前的前端高性能優化(一)、(二)中也都簡單的說過,之所以在這再次提及是因為確實覺得這個工具用著很舒服。
沒錯,就是舒服。
隨著信息爆炸時代的到來,網站本身性能也深刻影響著公司的形象、利益等問題。但是大多數前端測試工具都太**碎片化**,沒有辦法針對**多個使用場景**,而且很多都是像 yslow 這樣簡單打個分,也不是真實的用戶體驗。前一段時間在網上找到了一款前端性能優化分析工具——Browser Insight,裏麵的功能相當全麵,而且可以針對多個使用場景,包括:**PC端,移動微信,移動瀏覽器,移動webview**,還是 真實的用戶體驗,也就是說,用戶訪問你的網頁是什麼樣的,從這個工具中體現出的就是什麼樣子的。
基於 JavaScript 這個維度 Bi 做的也是相當豐富了。
首先是 腳本錯誤 板塊。Bi 裏麵可以從不同的時間維度查看被監控頁麵出現過的腳本錯誤,具體信息包括:**發生時間、設備類型、報錯的瀏覽器及其版本號、錯誤堆棧信息**都可以看到,不論是 線上還是線下測試或者頁麵維護 都是夠用了。
不但能看到時間、係統、瀏覽器等,還可以具體定位到出錯的**代碼行**,這個確實很方便。
其次是**頁麵響應時間**板塊,這個算是意外的收獲了。通過響應時間板塊裏麵的慢加載追蹤,可以看到本次慢加載的**頁麵資源加載**情況,然後我們就知道該優化哪個頁麵的哪些 js 、css、img等。
五.前端優化?用戶體驗?
各位看客,如果你真能堅持看到這裏,是否會覺得這篇更像解決**用戶體驗**問題的文章?但是講心裏話,前端優化的最終目的,難道不是為了改善用戶體驗嗎?
任何基於用戶體驗的方案,都可以叫前端優化技術。
不管使用多麼好的機器、多麼高的技術,響應速度問題總是避免不了的,因此糾結於什麼技術來解決是不實際的。但是有一款好的工具,使用一些小技巧,也可以改善用戶等待的體驗。
比如,我們為每個非 _target 的超鏈接或者表單的點擊,添加點擊事件處理,處理邏輯也很簡單,就是設置 3 秒超時,顯示等待對話框。如果在 3 秒內頁麵發生跳轉,那麼這個等待對話框就不會出現,否則會彈出提示用戶等待,從而及時的將響應反饋給用戶,減少用戶空白等待時間。
這並不是什麼高深的技術,但是運用這個技巧,卻可以大大的改善用戶體驗。
各位,我們優化的目的,就是不要讓用戶一直得不到響應,避免空白等待,讓用戶體驗越來越好。
最後更新:2017-04-01 13:44:32