注:本文是純技術探討文,無圖無笑點,但願您喜歡css
軟件行業極其缺少前端人才這是圈內的共識了,某種程度上講,同等水平前端的工資都要比後端高上很多,而圈內的另外一項共識則是——網頁是公司的臉面!html
幾年前,谷歌的一項統計代表,若是亞馬遜頁面加載每慢 100ms,將影響他們 1% 的收入;若是谷歌頁面加載慢 500ms,流量將銳減 20%,這個數據如今必將更加恐怖!前端
在前端高性能優化(一)、(二)中,筆者介紹了一些關於前端優化的技術,這些技術都依賴於前人的辛苦努力,但咱們仍要明白的是,前端的狀況十分複雜,優化前端性能是必須因地制宜、因時制宜。web
在本篇文章中,主要介紹的就是在一些條件下,傳統優化 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 的位置問題對網頁網站性能的影響。
爲何要考慮位置問題?
其實無論是 CSS 仍是 JavaScript,都須要考慮位置的問題,由於 HTML 的渲染和加載順序是從上往下,也就是若是前面插入了 JavaScript 的引用,那麼必須等到這個 JavaScript 下載完畢纔會渲染後續的部分。
所以 JavaScript 的插入位置就成爲一個值得考慮的問題,由於不適合的位置可能引發渲染的延遲等,形成很差的用戶體驗。
傳統方案帶來的問題和思考
CSS 放在頭部,JavaScript 放在尾部,這是傳統的經驗,它的好處是可讓頁面優先渲染, 從而頁面能夠快速顯示。
但有事實每每沒有咱們預想的那麼美好。
有的時候會出現這麼一種狀況:當頁面已經渲染完畢時,咱們馬上去使用網站的功能,但不少時候 功能按鈕會沒有反應。緣由也很簡單,就是 JavaScript 放在頁面的尾部,還沒來得及加載。。。。
這就糾結了。。。。
兩種 JavaScript 放置方式,一種放在頭部,一種放在尾部(暫時忽略部分放在頭部,部分放在尾部的方式),一個犧牲了渲染速度,一個犧牲了用戶體驗。因此不少時候 js 的問題咱們須要作權衡。
對通常的小型網站來講,用戶體驗問題要遠遠大於頁面渲染的問題,就好比上文提到的那種功能按鈕不可用的狀況。並且,若是 JavaScript 不是很大的話,放在頭部就很好,既不會有過久的頁面空白,也能讓其優先加載,兩者獲得了很好的平衡。
所以,不少經驗上的東西並非絕對的,必定要根據實際的狀況,包括功能特色、服務器網絡狀況等來綜合考慮。
爲此,筆者寫下一個自認爲較爲合理的位置選擇方案,僅供參考。
圖 1. 判斷 JavaScript 放置位置決策表
從上面的分類介紹,咱們也能夠看出,將功能代碼按類型歸類到不一樣的 JavaScript 文件是多麼的重要,好比應該放頭部和應該放尾部的代碼,最好不要合併在一塊兒,不要等到出問題要優化的時候再去整理和重構,這樣會增長不少沒必要要的工做量。
這不只僅是爲本身工做負責,也是爲後面要讀你代碼的新人負責。養成好的設計編碼習慣,也是技術積累的一部分。最後再根據 JavaScript 文件的功能類型,來決定是放在頁面的頭部仍是尾部。
這個問題在以前的前端高性能優化(一)、(二)中也都簡單的說過,之因此在這再次說起是由於確實以爲這個工具用着很舒服。
沒錯,就是舒服。
隨着信息爆炸時代的到來,網站自己性能也深入影響着公司的形象、利益等問題。可是大多數前端測試工具都太碎片化,沒有辦法針對多個使用場景,並且不少都是像 yslow 這樣簡單打個分,也不是真實的用戶體驗。前一段時間在網上找到了一款前端性能優化分析工具——Browser Insight,裏面的功能至關全面,並且能夠針對多個使用場景,包括:PC端,移動微信,移動瀏覽器,移動webview,仍是 真實的用戶體驗,也就是說,用戶訪問你的網頁是什麼樣的,從這個工具中體現出的就是什麼樣子的。
基於 JavaScript 這個維度 Bi 作的也是至關豐富了。
首先是 腳本錯誤 板塊。Bi 裏面能夠從不一樣的時間維度查看被監控頁面出現過的腳本錯誤,具體信息包括:發生時間、設備類型、報錯的瀏覽器及其版本號、錯誤堆棧信息均可以看到,不管是 線上仍是線下測試或者頁面維護 都是夠用了。
不但能看到時間、系統、瀏覽器等,還能夠具體定位到出錯的代碼行,這個確實很方便。
圖 2.Bi 腳本錯誤
其次是頁面響應時間板塊,這個算是意外的收穫了。經過響應時間板塊裏面的慢加載追蹤,能夠看到本次慢加載的頁面資源加載狀況,而後咱們就知道該優化哪一個頁面的哪些 js 、css、img等。
圖 3.Bi 資源列表-時序圖
各位看客,若是你真能堅持看到這裏,是否會以爲這篇更像解決用戶體驗問題的文章?可是講內心話,前端優化的最終目的,難道不是爲了改善用戶體驗嗎?
任何基於用戶體驗的方案,均可以叫前端優化技術。
無論使用多麼好的機器、多麼高的技術,響應速度問題老是避免不了的,所以糾結於什麼技術來解決是不實際的。可是有一款好的工具,使用一些小技巧,也能夠改善用戶等待的體驗。
好比,咱們爲每一個非 _target 的超連接或者表單的點擊,添加點擊事件處理,處理邏輯也很簡單,就是設置 3 秒超時,顯示等待對話框。若是在 3 秒內頁面發生跳轉,那麼這個等待對話框就不會出現,不然會彈出提示用戶等待,從而及時的將響應反饋給用戶,減小用戶空白等待時間。
這並非什麼高深的技術,可是運用這個技巧,卻能夠大大的改善用戶體驗。
各位,咱們優化的目的,就是不要讓用戶一直得不到響應,避免空白等待,讓用戶體驗愈來愈好。