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