本文作者:ziven 鄭成忠
原創宣告:本文為閱文前端團隊 YFE 成員出品,請尊重原創,轉載請聯絡公眾號 ( id: yuewen_YFE ) 獲取授權,並註明作者、出處和連結。
前端重構程式設計師是一個關注程式碼同時還要留意體驗的異類。程式碼的優化雖然難,但是有比較多的效能測試工具去證明優化的成果。然而體驗這種東西,我們又要如何去證明它的好與壞呢?
一、視覺體驗優化
- 頁面載入
- 資料請求
- 圖片渲染
二、資料證明體驗效果
今天我著重會基於「webnovel」PC站點從以上兩點給大家介紹,如何從體驗的角度去做重構的優化,並如何用資料去證明你的優化是有效果的。
一、視覺體驗優化
我們要做體驗的優化,首先要我們要知道什麼才是好的體驗。
不知道哪裡聽過這麼一句話,「 好的體驗,就是感覺不到在體驗 」。這句話聽起來很矛盾,但是卻和業界公認的體驗小紅書「 Don’t make me think 」的理念一樣。你想使用者來「 webnovel 」是來看小說的,不是來稱讚我們網頁體驗做得多麼優秀的。當使用者開始關注到我們網站體驗的時候,那正是說明我們的體驗不好的時候。
那使用者在什麼地方容易感受到我們網站的體驗呢?
頁面載入
第一個地方就是頁面載入的時候。這裡我們明顯可以看到「 webnovel 」的 Logo 和三個小圖示在頁面重新整理的時候,會有一瞬間從無到有的過程。
我們「 webnovel 」站點是面向全球海外使用者的,跳出了國內相容 IE 瀏覽器的怪圈,於是在小圖示這塊我們選擇了瀏覽器相容性要求高,但是呈現效果卻更好的SVG圖示「 SVG 屬於向量圖示,在能保證體積更小的情況下,還能在放大縮小的時候不失真 」。我們將 Iconfont 「來自阿里的線上圖示管理工具 」自動幫我們生成的 JS 程式碼引用到頁面中,結果就出現了上面的呈現效果。
這個原理其實很簡單,我們 SVG 圖示的 DOM 結構是在 JS 執行之後動態新增到我們的標籤內部的。所以就會出現先呈現頁面,再呈現圖示的效果。於是我們很自然的想到,直接將 JS 生成的 DOM 結構放到我們的內部,來解決這個問題。
但是很傻很天真,在拷貝 DOM 結構的時候我們發現,這個 SVG 程式碼量也太多了,直接放到頁面內部會大大增加我們 HTML 的程式碼量,影響整個頁面呈現的速度,這個感覺是撿了芝麻丟西瓜。
最後我們採用的解決方案是,把 SVG 圖示做了拆分,首屏的顯示的圖示我們採用直接新增 DOM 的方式,其它剩餘的圖示還是選擇 JS 動態載入老方法。這樣首屏之外的圖示即使有閃動使用者也很難看到。於是我們解決了首屏圖示閃動的問題,也避免了 SVG 圖示程式碼量的問題。使用者感知不到圖示的閃動,也就不會花時間去思考我們頁面載入是快是慢的體驗問題了。
提前載入首屏資料,能一定程度上增強我們使用者重新整理和跳轉頁面時候的體驗。
資料請求
第二個地方的就是我們資料請求的時候。當我們切換TAB的時候,能明顯看到一個 Loading 的效果。使用者的動作觸發資料請求,在等待的過程我們用 Loading 來告知使用者這一狀態,以減弱使用者等待的焦慮。這其實是一個對於資料載入,增強體驗常規的做法。
可是不管我們的資料請求多麼的快,使用者都還是能明顯能看到這個 Loading 的效果。這並不是我們想要的。
我們這邊處理的辦法是,在使用者滑鼠放到這個按鈕的時候,我們認為使用者是有了點選的意願,於是我們就提前發起了資料請求的操作。當使用者按下這個按鈕的時候,我們的資料請求的整個過程可能已經結束,而這也就意味著我們的 Loading 狀態已經消失。此時使用者就能直接看到我們載入好的資料了。也就是說很有可能,在整個過程中使用者是看到不到我們的 Loading 狀態的。這不就是我們想要的體驗上的優化嗎?
利用使用者操作的空閒時間,提前做一些預處理,不失為一個增強資料請求體驗的好辦法。
圖片渲染
我們都知道,圖片和圖示都是屬於展示性的元素,特別是像我們 「 webnovel 」網站設計師很用心製作的書封,我們自然會願意選擇體積更大但是質量更高的高清圖。為了避免影響正文的展示,我們又不得不選擇了類似圖片 Lazyload 的機制,讓這個圖片延遲載入。
但是可以明顯看到這和之前的資料載入的 Loading 邏輯一樣,需要一個表示 Loading 態的佔點陣圖。等圖片載入完成,佔點陣圖會一瞬間被我們的高清書封替換,於是此時就出現了我們不期望的閃動。
當使用者一看到閃動,他們就會去思考你這個載入是快還是慢。但是我們要的是 「Don’t make me think 」。我們不希望讓使用者去思考除開我們產品之外的東西。所以我們得想個辦法弱化甚至去除這種閃動。
講到這裡呢就不得不科普以下我們瀏覽器本身就有的圖片快取機制了。在一定時間段內你瀏覽器訪問過的圖片,會被瀏覽器快取。當你再一次看到這個圖片的時候,這個圖片就直接讀取瀏覽器快取的內容一瞬就開啟,不會有閃動問題。
於是我們就想是不是可以利用這個機制,解決之前閃動的問題。但是現在難點是,我們詳情頁的書封是比首頁的書封大的。因為尺寸不一樣所以是不同的圖片,於是就沒有快取這個概念。
如果我們讓詳情頁也用首頁的書封,詳情頁小圖被拉伸就會看起來很模糊。如果首頁用詳情頁的大書封,首頁的圖片資料載入開銷又太大。
我們這邊採用的解決方案是,三層疊加法。我們把佔點陣圖,小書封,大書封,按照上圖的層級完美的疊在了同一個位置。當使用者從首頁進入到我們詳情頁的時候,我們佔點陣圖和小書封都是直接使用瀏覽器快取瞬間呈現的,因為小書封是疊在佔點陣圖之上的,所以使用者是看不到佔點陣圖的。而此時大書封正在載入,當大書封載入好了之後,就會蓋在小書封之上。等使用者仔細看這個書封的時候,這個大書封其實很有可能已經載入完成。
從上圖的GIF可以看出,整個過程就從之前的佔點陣圖到大書封的閃現,變成了現在的小書封到大書封的漸變。其實這是很難被使用者發現的。
看到這裡可能有同學會問說,既然這裡都看不到佔點陣圖,為什麼還需要載入這個圖呢?其實原因很簡單,因為不是每個人都是從首頁進入到詳情頁的。有可能使用者是直接開啟的這個連結。那麼此時佔點陣圖就回到了最初的邏輯。先看到佔點陣圖然後再看到書封。當然我也得承認對於這樣的使用者,我們其實是多載入了一個小書封的資源的。但是對於體驗上的優化來說,這一點資源的消耗我個人認為還是可以接受的。
還有一個好玩兒的點是,在這個地方因為同時載入了,佔點陣圖,小書封,大書封,它們作為圖片也都會被瀏覽器快取,當使用者跳轉到其它頁面的時候,如果有相同的圖片,那又是瞬開的。這樣我們就充分的利用了瀏覽器快取,讓使用者在我們網站上的體驗得到了進一步的提升。
圖片快取,讓網站體驗比好更好。
二、資料證明體驗效果
視覺層的體驗優化是所見即所得的,你可以很快的看到優化的成果。但是有很多因為瀏覽器差異,或者使用者差異引起的體驗問題,我們沒法直觀和快速的去證明體驗優化的效果。我們就得靠資料去證明了。
要用資料說話,首先我們得有資料,而這個資料的收集工具我們海外 PC 站用的則交給了來自 Google 的 Analytics。這邊給大家講關於這個的一個有趣故事。
有一天我在用 webpagetest 「 一個全球知名的測試網站載入速度的工具 」測試我們 「 webnovel 」頁面的時候我看到了這樣一個結果。
大家注意看那個最長的綠色,看到了吧,一個 DNS 載入怎麼比後面的 SSL + CSS 載入 + CSS渲染還要長?CSS 可是強制阻塞我們頁面渲染的重要元素,它要是慢了,你網站做再多優化都沒有用。這個你讓人怎麼忍?
怎麼辦呢?我們選擇了一個暴力但是有效的辦法,直接把 CSS 合併到我們的 HTML 檔案中 「 CSS 內聯到 HTML 內部 」。CSS 檔案都沒有了,看你還怎麼 DNS、SSL … 哇!好棒,我拿著這個去找老大邀功。老大啪啪給我提了兩個點就把我打懵了。
第一, 你這個明顯是首次載入頁面時候的效果,對於大多數這個 CSS 檔案已經有快取的使用者,你如何證明,這個優化對他們是又用的?
第二,「 webnovel 」是面向全球的網站,你又如何證明,這個優化對所有地區的使用者的優化力度 ?
是啊我要怎麼證明?「 webnovel 」全球這麼多的使用者,我就用一份 「 webpagetest 」 的測試報告去涵蓋所有的終端和使用者群體,顯示是不具有公信力的。並且我又要如何證明這個優化的力度是多少?
此時中國好同事出現了,我的前端邏輯小夥伴幫我在框架機內部做了一個隨機預處理的AB樣本輸出。道理很簡單,就是讓 50% 的使用者是用原始的方式載入我們的 CSS ,另外 50% 的使用者使用我們 CSS 內聯到 HTML 內部的方式。這樣我只需要加個識別符號區別一下這兩個樣本,上報到 GA 「 Google Analytics 」 ,然後 GA 會自動幫我們統計和處理這些樣本,最後我只需要將這兩個樣本的平均值做一個 10 以內的減法,就知道了我們的優化力度具體是多少了。
然而另一個問題出現了,我們應該把什麼作為資料上報給 GA 呢?顯然用整個網頁的載入時間去證明 CSS 的載入是不對的。那我用 CSS 載入完成之後的那個時間去證明?可是我又怎麼能證明 CSS 載入完成之後頁面就已經渲染好了呢?我們不是在做體驗的優化嗎?又怎麼能僅憑藉 CSS 檔案的載入來證明使用者體驗變好了呢?
此時我是凌亂的。不行,整個場面我要HOLD住,不能慌。
體驗,體驗,CSS都沒有載入,使用者連頁面都沒有看到又怎麼能叫體驗?於是使用者剛看到頁面的時間,被我認定是一定程度上可以證明體驗優劣的。
怎麼去獲取這個時間呢?其實利用 performance API,就可以獲取到上圖所示的瀏覽器各個階段的時間。
Chrome瀏覽器 可以用 window.chrome.loadTimes().firstPaintTime; IE8+ 瀏覽器可以用 window.performance.timing.msFirstPaint;
來獲取頁面開始渲染的時間。最後大家一致的意見是,將這個 「 firstPaintTime - navigationStart 」的時間近似理解為使用者從訪問頁面到看到頁面的時間。
於是,我很開心的把這個這個時間上報到 GA,然後版本上線,等待資料收集。最後得出如下的統計結果:
看到以上的資料結果,這個優化的時間和總時間比起來比預想的差太多了。感覺不應該啊?
當我們仔細分析這個資料,發現在這整個的時間段內,服務端的時間佔了 1.1s 。我在這拼命的優化體驗,可是最後發現體驗的瓶頸並不在我們前端這邊。這充分的說明,有的東西還是得靠資料說話,而不是你以為你以為的就是你以為的。當然除開這個瓶頸時間我們可以得出如下的結論。
至此我們有理有據的證明了優化體驗的成果,雖然結果出乎了我們的預料,但是卻證明,資料上報是能夠證明我們體驗成果的一個有理證據。
當然我們也把這個瓶頸問題,反饋給力服務端的同學。然後得到的答覆是,「 webnovel 」還屬於我們海外站的新專案,很多海外伺服器有待跟進。相信在後續裝置之後,會解決這個痛點。
資料上報,讓你的體驗優化有理有據。
總結
篇幅有限,這邊我只是零散的列舉了,我個人認為可以從使用者體驗角度去做的幾點重構優化,以及如何利用資料去證明你優化的力度。希望對於大家有一定的啟發和幫助,有什麼問題,也請給我留言,我們可以深入的交流。