在網路的世界裡,我們只要輸入網址就可以進行瀏覽,但是輸入網址之後、為了要顯示網站的內容,我們可能必須擷取幾十個,甚至是數百個不同的資源(加起來高達幾百萬位元組的資料量)才能夠顯示內容。
為了提供網站具備卓越的效能,我們必須在幾百毫秒內彙整資訊並 render 出畫面,才能夠實現即時搜尋的瀏覽體驗。
雖然網際網路速度越來越快,但在不同國家或地區所提供的網路環境速度不盡相同,仍然有許多使用者受限於網路訊號不佳和昂貴的網路費用,所以我們更需要有效率地去組織你的網站內容,去檢視是否達成『Optimizing Content Efficiency』所提到的優化方向:
為了提供使用者優異的瀏覽體驗,我們需要刪除網站內不必要的資源(可能包括圖片、HTML、CSS、Javascript 等靜態資源),雖然這是一件相當基本的工作,但卻非常容易被忽略。
例如,我們的網站裡有一張貓咪圖片
1: 我們需要評估顯示這張圖片所帶來的下載成本以及為使用者提供的價值是否符合正比?
執行方向: 在前期網站規劃時,工程師和 PM /網站決策者,進行討論。
2: 假使這張圖片是外部網站的資源,能否確定具有穩定的效能?
執行方向: 假設為外部圖片、在穩定度極低的情況下,應該審慎決定該張圖片是否有存在的必要。
3: 這張圖片如果無法使用,是否會影響到網站效能和使用者體驗?
執行方向: 若圖片無法使用,當然可以請設計師提供墊檔圖、讓前端工程師判斷顯示內容,但如果請求資源時、server 沒有回應,則會影響網站效能。
4: 這張圖片是否可以做技術上的處理(壓縮、快取等),提高下載的效能?
執行方向: 在一般情況下,SA/後端/前端工程師都可以從不同層面去優化圖片,但若是外部圖片、可能會無法控制圖片的品質,進而降低網站的效能。
我們的網頁往往會包含一些不必要的資源,更糟的是、有些資源會影響到網站的效能,同時也沒辦法帶給使用者太大的價值。
再舉一個例子:
網站決定要新增 Carousel ,點擊一下可以瀏覽更多照片,所有照片都會被下載。
問題:
我們是否可以統計有多少使用者實際使用 Carousel 來查看照片?
根據 ND.edu 研究 指出,在 Carousel 第一個位置的點擊,佔了 89.1%,也就是說大部分使用者會下載大量不會被瀏覽到的圖片。
當我們加入新的資源或功能,應該要觀察使用者點擊或瀏覽的使用次數,移除不必要的服務,避免為網站帶來不必要的效能成本。
PWA 的目標是創造更好的使用者體驗,而這不只是前端工程師的工作,如果我們能夠瞭解在各種層面上的解決辦法,作為一位前端工程師、提出更好的建議,幫助網站變得更好。
我們應該定期檢視網站的資源如下:
經過縝密的評估再針對網站上的資源做處理,如此才可確保每種資源都能為使用者提供更優異的體驗。
網頁主要由 HTML、CSS、JavaScript 所組成,我們可以透過一些工具,重新組織檔案。
例如:
addClass: function( value ) {
var classes, elem, cur, curValue, clazz, j, finalValue,
i = 0;
if ( jQuery.isFunction( value ) ) {
return this.each( function( j ) {
jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
} );
}
if ( typeof value === "string" && value ) {
classes = value.match( rnotwhite ) || [];
while ( ( elem = this[ i++ ] ) ) {
curValue = getClass( elem );
cur = elem.nodeType === 1 &&
( " " + curValue + " " ).replace( rclass, " " );
if ( cur ) {
j = 0;
while ( ( clazz = classes[ j++ ] ) ) {
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
cur += clazz + " ";
}
}
// Only assign if different to avoid unneeded rendering.
finalValue = jQuery.trim( cur );
if ( curValue !== finalValue ) {
elem.setAttribute( "class", finalValue );
}
}
}
}
return this;
}
透過一些 Minify 工具會變成:
addClass:function(value){var classes,elem,cur,curValue,clazz,j,finalValue,i=0;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,getClass(this)))})}
if(typeof value==="string"&&value){classes=value.match(rnotwhite)||[];while((elem=this[i++])){curValue=getClass(elem);cur=elem.nodeType===1&&(" "+curValue+" ").replace(rclass," ");if(cur){j=0;while((clazz=classes[j++])){if(cur.indexOf(" "+clazz+" ")<0){cur+=clazz+" "}}
finalValue=jQuery.trim(cur);if(curValue!==finalValue){elem.setAttribute("class",finalValue)}}}}
return this}
這些工具掌握資料格式及其屬性,會去刪除不必要的 code,移除空格和定位字元,但不會影響原本實際內容。
像是:
移除開發人員專用的『程式碼註解』,就能大幅縮減網頁的檔案大小
透過「智慧型」CSS 壓縮工具,合併 CSS
/* awesome-container is only used on the landing page */
.awesome-container { font-size: 120% }
.awesome-container { width: 50% }
變成
.awesome-container{font-size:120%width:50%}
例如:jQuery Core 2.2.4 未壓縮版本的檔案大小為 258KB,而壓縮後的大小為 86KB,相差將近三倍的檔案大小。
以上圖為例,透過 GZIP 壓縮,檔案大小節省了 24.8 KB。
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 612 792" xml:space="preserve">
<g id="XMLID_1_">
<g>
<circle fill="red" stroke="black" stroke-width="2" stroke-miterlimit="10" cx="50" cy="50" r="40"/>
</g>
</g>
</svg>
svgo 可將上述由 Illustrator 產生的 SVG 檔案大小縮減 58%,也可以使用 GZIP 壓縮、但要先確認 server 是否支援 SVG 格式。
我們可以透過 HTTP Etag 來實現瀏覽器快取,要實現這個功能並不難,只要藉由後端在 Response 的 Header 塞入 Etag 的相關屬性(Etag、Cache-Control)
以 Node.js Express 為例:
res.setHeader('ETag', '"' + hash + '"'); // hash 是個亂數
res.setHeader('Cache-Control', 'public, max-age=31557600');
今天分享 Optimizing Content Efficiency 的優化的方向,其實這件事情無法只靠前端就能夠實現,必須藉由整個團隊的配合才能達成,例如:後端的 Response Header 處理、伺服器的設定,甚至是網站需求的取捨...等等。
本人小小筆記,如有錯誤或需要改進的部分,歡迎給予回饋。
我將會用最快的速度修正,m(_ _)m。謝謝
以上圖為例,透過 GZIP 壓縮,檔案大小節省了 24.8 KB。
142KB 減 43.2KB 不是 24.8KB
應該是 98.8KB