文章原本是給公司內部分享用的,如今發表出來,歡迎你們提出寶貴建議。css
按粒度分爲兩類:html
頁面級別的優化目標基本就是如何減小HTTP請求數,減小請求資源的體積。每一個請求都是有成本的,既包含時間成本也包含資源成本(一個完整的請求都須要通過DNS尋址、與服務器創建鏈接、發送數據、等待服務器響應、接收數據這樣一個 「漫長」 而又複雜的過程)前端
根據靜態文件的類型,能夠藉助gulp工具將js文件和css文件進行合併和壓縮。 例如官網項目裏css文件有七個,js文件有十幾二十多個,合併壓縮靜態資源後能夠減小http的開銷。 jquery
lazyload
插件實現圖片懶加載。等滾動條滾動到對應的地方再加載所須要的圖片資源。devicePixelRatio
檢查設備的像素比,輔助區分視網膜設備仍是非視網膜設備來決定加載兩倍圖仍是原始大小的圖片。gulp-imagemin
工具壓縮下大小。icon-font
來實現。或者直接在頁面寫svg代碼和轉成base64寫到頁面也行,總之是要減小http的請求數。
將首屏第一時間呈現給用戶。 具體的作法是除了首屏dom元素以外,將全部的dom元素用一個template
元素進行包裹,等window監聽到load事件後,將剩餘的dom部分所有插到頁面中。(tips:爲避免用戶可能還沒等到window的load事件就開始滾動頁面,能夠將首屏的範圍擴大。)web
DNS預讀取是一項使瀏覽器主動去執行域名解析的功能。DNS請求須要的帶寬很是小,可是延遲卻有點高。 下面是引用MDN的一句話:chrome
在某些瀏覽器中這個預讀取的行爲將會與頁面實際內容並行發生(而不是串行)。正因如此,某些高延遲的域名的解析過程纔不會卡住資源的加載。 這樣能夠極大的加速(尤爲是移動網絡環境下)頁面的加載。在某些圖片較多的頁面中,在發起圖片加載請求以前預先把域名解析好將會有至少 5% 的圖片加載速度提高。gulp
具體作法: head
標籤里加上瀏覽器
<link rel="dns-prefetch" href="https://data.dadaabc.com/">
複製代碼
data.dadaabc.com
爲靜態資源的域名,如還有其餘連接的域名,都一塊兒加進去。緩存
同域下瀏覽器能併發的請求有限,爲了增長併發,尤爲是一些靜態資源上,可使用多個域名。但因爲域名DNS解析自己也是耗時的,因此也不是越多越好,chrome最大支持6路併發,因此通常設置2-4個域名較爲合適。 具體的作法是:再增長cdn域名來下載靜態資源。好比圖片所有用img.dadaabc.com/
域名,css資源所有用css.dadaabc.com/
域名,這些域名最終所有指向一樣的cdn服務器。靜態資源域名加前綴能夠用gulp-rev-replace
來實現。bash
統計代碼所有放到window的load事件以後執行。爲了便於管理統計代碼,例如頁面加上一些埋點,增長刪除統計產品,咱們能夠藉助Google Tag Manager
工具來統一管理。 具體作法是:頁面只拉取Google Tag Manager
提供的gtm
代碼,該js代碼含有所有的統計產品,例如百度、Inspelect等, 這些統計產品也都是經過建立script標籤來動態插入到頁面中的。另外須要注意的是,google提供的gtm
代碼是在google服務器上的,爲了讓獲取該代碼的速度更快,咱們能夠在本身的服務器上執行crontab
定時任務,每分鐘獲取一次,而後gtm
代碼直接從本身服務器上獲取。
css文件所有放到head
裏,script文件所有放到body
的最底部。 緣由: 把樣式表移到head
裏容許頁面逐步渲染。 瀏覽器負責渲染的GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(至關於被凍結了),GUI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。
#####多個屬性改變一次性寫: 舉個例子:
var ele = document.getElementById('myDiv');
ele.style.borderLeft = '1px';
ele.style.borderRight = '2px';
ele.style.padding = '5px';
複製代碼
三個樣式屬性被改變,每個都會影響元素的幾何結構,雖然大部分現代瀏覽器都作了優化,只會引發一次重排,可是像上文同樣,若是一個及時的屬性被請求,那麼就會強制刷新隊列,並且這段代碼四次訪問DOM,一個很顯然的優化策略就是把它們的操做合成一次,這樣只會修改DOM一次:
var ele = document.getElementById('myDiv');
ele.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';
複製代碼
總結:同一個DOM的多個屬性改變能夠寫在一塊兒(減小DOM訪問,同時把強制渲染隊列刷新的風險降爲0)
fragment是個輕量級的document對象,它的設計初衷就是爲了完成更新和移動節點這樣的任務。fragment的一個便利的語法特性是當你附加一個片段到節點時,實際上被添加的是該片段的子節點,而不是片段自己。只觸發了一次重排,並且只訪問了一次實時的DOM。 例如:
var fragment = document.createDocumentFragment();
var li = document.createElement('li');
li.innerHTML = 'apple';
fragment.appendChild(li);
var li = document.createElement('li');
li.innerHTML = 'watermelon';
fragment.appendChild(li);
document.getElementById('fruit').appendChild(fragment);
複製代碼
觸發大量回調函數的事件,例如拖拽時的mousemove
事件,window對象的resize
、scroll
事件,文字輸入、自動完成的keyup
事件等,須要合理使用函數防抖和函數節流機制。具體能夠參考個人另一篇文章函數防抖和函數節流
CSS選擇器的解析式實際上是從右到左的,例如:
#div1 a {
color: red
}
複製代碼
如上面的選擇器,瀏覽器必須遍歷查找全部的a元素,再去找ID爲div1的元素,這樣查找的方式顯然很低效。
參考資料: Web前端應該從哪些方面來優化網站? 重排和重繪