Html部分
1.語(yǔ)義化HTML:好處在于可以使代碼簡(jiǎn)潔清晰,支持不同設(shè)備,利于搜索引擎啰劲,便于團(tuán)隊(duì)開(kāi)發(fā)葵蒂;
2.減少DOM節(jié)點(diǎn):加速頁(yè)面渲染交播;
3.給圖片加上正確的寬高值:這可以減少頁(yè)面重繪,同時(shí)防止圖片縮放践付;
4.防止src屬性和link的href屬性為空:當(dāng)值為空時(shí)秦士,瀏覽器很可能會(huì)把當(dāng)前頁(yè)面當(dāng)成其屬性值加載;
5.正確的閉合標(biāo)簽:如避免使用<div/>永高,瀏覽器會(huì)多一個(gè)將它解析成<div></div>的過(guò)程隧土;
6.鏈接為目錄或首頁(yè)的地址后面加”/”,如http://www.qq.com/命爬;
7.用LINK而不用@import方式導(dǎo)入樣式曹傀;
8.樣式放在頁(yè)頭,JS放在頁(yè)尾饲宛;
9.縮小favicon.ico并緩存皆愉;
CSS部分
1.避免使用 CSS Expressions(CSS表達(dá)式):如
2.避免使用 CSS Filter(CSS濾鏡);
3.使用CSS縮寫,減少代碼量亥啦;
4.通過(guò)CSSSprites把同類圖片合成一張炭剪,減少圖片請(qǐng)求;
5.減少查詢層級(jí):如.header .logo要好過(guò).header .top .logo翔脱;
6.減少查詢范圍:如.header>li要好過(guò).header li奴拦;
7.避免TAG標(biāo)簽與CLASS或ID并存:如a.top、button#submit届吁;
8.刪除重復(fù)的CSS错妖;
栗子:
id選擇器(#myid)
類選擇器(.myclassname)
標(biāo)簽選擇器(div,h1,p)
相鄰選擇器(h1+p)
子選擇器(ul > li)
后代選擇器(li a)
通配符選擇器(*)
屬性選擇器(a[rel="external"])
偽類選擇器(a:hover,li:nth-child)
Javscript部分
1.盡量少用全局變量;
2.使用事件代理綁定事件疚沐,如將事件綁定在body上進(jìn)行代理暂氯;
3.避免頻繁操作DOM節(jié)點(diǎn);
4.不使用EVAL亮蛔;
5.減少對(duì)象查找痴施,如a.b.c.d這種查找方式非常耗性能,盡可能把它定義在變量里究流;
6.類型轉(zhuǎn)換:把數(shù)字轉(zhuǎn)換成字符串使用”” + 1辣吃,浮點(diǎn)數(shù)轉(zhuǎn)換成整型使用Math.floor()或者M(jìn)ath.round();
7.對(duì)字符串進(jìn)行循環(huán)操作芬探,譬如替換神得、查找,應(yīng)使用正則表達(dá)式偷仿;
8.刪除重復(fù)的JS哩簿;
其中,值得一提的是:
1酝静、使用requestAnimationFrame來(lái)替代setTimeout和setInterval
希望在每一幀剛開(kāi)始的時(shí)候?qū)?yè)面進(jìn)行更改节榜,目前只有使用 requestAnimationFrame 能夠保證這一點(diǎn)。使用 setTimeout 或者 setInterval 來(lái)觸發(fā)更新頁(yè)面的函數(shù)形入,該函數(shù)可能在一幀的中間或者結(jié)束的時(shí)間點(diǎn)上調(diào)用全跨,進(jìn)而導(dǎo)致該幀后面需要進(jìn)行的事情沒(méi)有完成,引發(fā)丟幀
2亿遂、使用IntersectionObserver來(lái)實(shí)現(xiàn)圖片可視區(qū)域的懶加載
傳統(tǒng)的做法中浓若,需要使用scroll事件,并調(diào)用getBoundingClientRect方法蛇数,來(lái)實(shí)現(xiàn)可視區(qū)域的判斷挪钓,即使使用了函數(shù)節(jié)流,也會(huì)造成頁(yè)面回流耳舅。使用IntersectionObserver碌上,則沒(méi)有上述問(wèn)題
3倚评、使用web worker
客戶端javascript一個(gè)基本的特性是單線程:比如,瀏覽器無(wú)法同時(shí)運(yùn)行兩個(gè)事件處理程序馏予,它也無(wú)法在一個(gè)事件處理程序運(yùn)行的時(shí)候觸發(fā)一個(gè)計(jì)時(shí)器天梧。Web Worker是HTML5提供的一個(gè)javascript多線程解決方案,可以將一些大計(jì)算量的代碼交由web Worker運(yùn)行霞丧,從而避免阻塞用戶界面呢岗,在執(zhí)行復(fù)雜計(jì)算和數(shù)據(jù)處理時(shí),這個(gè)API非常有用
服務(wù)器部分
1.盡量合并CSS蛹尝、JS文件后豫,或?qū)⑵渲苯訉懺陧?yè)面上,減少HTTP請(qǐng)求突那;
2.壓縮CSS挫酿、JS文件,縮短文件傳輸時(shí)間愕难;
3.避免404錯(cuò)誤:特別要避免給404指定一個(gè)停擺頁(yè)面早龟,否則所有404錯(cuò)誤都將會(huì)加載一次頁(yè)面;
4.一般要求減少DNS查詢次數(shù)猫缭,如同一個(gè)頁(yè)面的請(qǐng)求資源盡量少的使用不同的主機(jī)名拄衰,這可以減少網(wǎng)站并行下載的數(shù)量,但很多網(wǎng)站為了加速下載資源其實(shí)是特意用了多個(gè)主機(jī)名饵骨,這里要做一個(gè)權(quán)衡;
5.使用CDN加速茫打,使用戶從離自己最近的服務(wù)器下載文件居触;
6.減少Cookie的大小,使用無(wú)cookie的域老赤,客戶端請(qǐng)求靜態(tài)文件的時(shí)候轮洋,減少 Cookie 的反復(fù)傳輸對(duì)主域名的影響;
7.為文件頭指定Expires抬旺,使內(nèi)容具有緩存性弊予;
8.使用gzip壓縮內(nèi)容;
DOM優(yōu)化
1开财、緩存DOM
const div = document.getElementById('div')
由于查詢DOM比較耗時(shí)汉柒,在同一個(gè)節(jié)點(diǎn)無(wú)需多次查詢的情況下,可以緩存DOM
2责鳍、減少DOM深度及DOM數(shù)量
HTML 中標(biāo)簽元素越多碾褂,標(biāo)簽的層級(jí)越深,瀏覽器解析DOM并繪制到瀏覽器中所花的時(shí)間就越長(zhǎng)历葛,所以應(yīng)盡可能保持 DOM 元素簡(jiǎn)潔和層級(jí)較少正塌。
3、批量操作DOM
由于DOM操作比較耗時(shí),且可能會(huì)造成回流乓诽,因此要避免頻繁操作DOM帜羊,可以批量操作DOM,先用字符串拼接完畢鸠天,再用innerHTML更新DOM
4讼育、批量操作CSS樣式
通過(guò)切換class或者使用元素的style.csstext屬性去批量操作元素樣式
5、在內(nèi)存中操作DOM
使用DocumentFragment對(duì)象粮宛,讓DOM操作發(fā)生在內(nèi)存中窥淆,而不是頁(yè)面上
6、DOM元素離線更新
對(duì)DOM進(jìn)行相關(guān)操作時(shí)巍杈,例忧饭、appendChild等都可以使用Document Fragment對(duì)象進(jìn)行離線操作,帶元素“組裝”完成后再一次插入頁(yè)面筷畦,或者使用display:none 對(duì)元素隱藏词裤,在元素“消失”后進(jìn)行相關(guān)操作
7、DOM讀寫分離
瀏覽器具有惰性渲染機(jī)制鳖宾,連接多次修改DOM可能只觸發(fā)瀏覽器的一次渲染吼砂。而如果修改DOM后,立即讀取DOM鼎文。為了保證讀取到正確的DOM值渔肩,會(huì)觸發(fā)瀏覽器的一次渲染。因此拇惋,修改DOM的操作要與訪問(wèn)DOM分開(kāi)進(jìn)行
8周偎、事件代理
事件代理是指將事件監(jiān)聽(tīng)器注冊(cè)在父級(jí)元素上,由于子元素的事件會(huì)通過(guò)事件冒泡的方式向上傳播到父節(jié)點(diǎn)撑帖,因此蓉坎,可以由父節(jié)點(diǎn)的監(jiān)聽(tīng)函數(shù)統(tǒng)一處理多個(gè)子元素的事件
利用事件代理,可以減少內(nèi)存使用胡嘿,提高性能及降低代碼復(fù)雜度
9蛉艾、防抖和節(jié)流
使用函數(shù)節(jié)流(throttle)或函數(shù)去抖(debounce),限制某一個(gè)方法的頻繁觸發(fā)
10衷敌、及時(shí)清理環(huán)境
及時(shí)消除對(duì)象引用勿侯,清除定時(shí)器,清除事件監(jiān)聽(tīng)器逢享,創(chuàng)建最小作用域變量罐监,可以及時(shí)回收內(nèi)存
webpack優(yōu)化
1.打包公共代碼
- 使用CommonsChunkPlugin插件,將公共模塊拆出來(lái)瞒爬,最終合成的文件能夠在最開(kāi)始的時(shí)候加載一次弓柱,便存到緩存中供后續(xù)使用沟堡。這會(huì)帶來(lái)速度上的提升,因?yàn)闉g覽器會(huì)迅速將公共的代碼從緩存中取出來(lái)矢空,而不是每次訪問(wèn)一個(gè)新頁(yè)面時(shí)航罗,再去加載一個(gè)更大的文件
- webpack 4 將移除 CommonsChunkPlugin, 取而代之的是兩個(gè)新的配置項(xiàng) optimization.splitChunks 和 optimization.runtimeChunk
- 通過(guò)設(shè)置 optimization.splitChunks.chunks: "all" 來(lái)啟動(dòng)默認(rèn)的代碼分割配置項(xiàng)
2.動(dòng)態(tài)導(dǎo)入和按需加載 - webpack提供了兩種技術(shù)通過(guò)模塊的內(nèi)聯(lián)函數(shù)調(diào)用來(lái)分離代碼,優(yōu)先選擇的方式是屁药,使用符合 ECMAScript 提案 的 import() 語(yǔ)法粥血。第二種,則是使用 webpack 特定的 require.ensure
3.剔除無(wú)用代碼 - tree shaking 是一個(gè)術(shù)語(yǔ)酿箭,通常用于描述移除 JavaScript 上下文中的未引用代碼(dead-code)复亏。它依賴于 ES2015 模塊系統(tǒng)中的靜態(tài)結(jié)構(gòu)特性,例如 import 和 export缭嫡。這個(gè)術(shù)語(yǔ)和概念實(shí)際上是興起于 ES2015 模塊打包工具 rollup
JS的tree主要通過(guò)uglifyjs插件來(lái)完成缔御,CSS的tree shaking主要通過(guò)purify CSS來(lái)實(shí)現(xiàn)的
4.長(zhǎng)緩存優(yōu)化 - 將hash替換為chunkhash,這樣當(dāng)chunk不變時(shí)妇蛀,緩存依然有效
- 使用Name而不是id
每個(gè) module.id 會(huì)基于默認(rèn)的解析順序(resolve order)進(jìn)行增量耕突。也就是說(shuō),當(dāng)解析順序發(fā)生變化评架,ID 也會(huì)隨之改變
下面來(lái)使用兩個(gè)插件解決這個(gè)問(wèn)題眷茁。第一個(gè)插件是 NamedModulesPlugin,將使用模塊的路徑纵诞,而不是數(shù)字標(biāo)識(shí)符上祈。雖然此插件有助于在開(kāi)發(fā)過(guò)程中輸出結(jié)果的可讀性,然而執(zhí)行時(shí)間會(huì)長(zhǎng)一些浙芙。第二個(gè)選擇是使用 HashedModuleIdsPlugin雇逞,推薦用于生產(chǎn)環(huán)境構(gòu)建
5.公用代碼內(nèi)聯(lián) - 使用html-webpack-inline-chunk-plugin插件將mainfest.js內(nèi)聯(lián)到html文件中
針對(duì)性的處理
圖片加載處理
圖片預(yù)加載
圖片懶加載
圖片壓縮(UI方面,導(dǎo)出時(shí)壓縮圖片)
雪碧圖
Base64
使用字體圖標(biāo)來(lái)代替圖片
預(yù)加載的意思就是提前加載內(nèi)容茁裙。而圖片的預(yù)加載往往會(huì)被用在圖片資源比較大,加載時(shí)會(huì)導(dǎo)致很長(zhǎng)的等待過(guò)程時(shí)节仿,才會(huì)被使用的晤锥。常見(jiàn)場(chǎng)景:圖片漫畫展示時(shí)。往往會(huì)預(yù)加載一張到兩張的圖片廊宪。
懶加載矾瘾,這種方式在開(kāi)發(fā)中會(huì)被經(jīng)常使用。首先箭启,我們需要明白一個(gè)道理:往往只有看到的資源是必須的壕翩,其他資源是可以隨著用戶的滾動(dòng),隨即顯示的傅寡。所以放妈,特別是對(duì)于圖片資源特別多的網(wǎng)站來(lái)說(shuō)北救,做好圖片的懶加載是可以大大提升網(wǎng)頁(yè)的載入速度的。
常見(jiàn)的圖片懶加載的方式就是:在最初給圖片的src設(shè)置一個(gè)比較簡(jiǎn)單的圖片芜抒,然后將圖片的真實(shí)地址設(shè)置給自定義的屬性珍策,做一個(gè)占位,然后給圖片設(shè)置監(jiān)聽(tīng)事件宅倒,一旦圖片到達(dá)視口范圍攘宙,從圖片的自定義屬性中獲取出真是地址,然后賦值給src拐迁,讓其進(jìn)行加載蹭劈。
雪碧圖:CSS雪碧圖是以前非常流行的技術(shù),把網(wǎng)站上的一些圖片整合到一張單獨(dú)的圖片中线召,可以減少網(wǎng)站的HTTP請(qǐng)求數(shù)量铺韧,但是當(dāng)整合圖片比較大時(shí),一次加載比較慢灶搜。隨著字體圖片祟蚀、SVG圖片的流行,該技術(shù)漸漸退出了歷史舞臺(tái)
Base64:將圖片的內(nèi)容以Base64格式內(nèi)嵌到HTML中割卖,可以減少HTTP請(qǐng)求數(shù)量前酿。但是,由于Base64編碼用8位字符表示信息中的6個(gè)位鹏溯,所以編碼后大小大約比原始值擴(kuò)大了 33%
使用字體圖標(biāo)來(lái)代替圖片
文件合并
如果不進(jìn)行文件合并罢维,有如下3個(gè)隱患
1、文件與文件之間有插入的上行請(qǐng)求丙挽,增加了N-1個(gè)網(wǎng)絡(luò)延遲
2肺孵、受丟包問(wèn)題影響更嚴(yán)重
3、經(jīng)過(guò)代理服務(wù)器時(shí)可能會(huì)被斷開(kāi)
但是颜阐,文件合并本身也有自己的問(wèn)題
1平窘、首屏渲染問(wèn)題
2、緩存失效問(wèn)題
所以凳怨,對(duì)于文件合并瑰艘,有如下改進(jìn)建議
1、公共庫(kù)合并
2肤舞、不同頁(yè)面單獨(dú)合并
移動(dòng)端優(yōu)化
1.長(zhǎng)列表滾動(dòng)優(yōu)化
2.函數(shù)防抖和函數(shù)節(jié)流
3.使用touchstart紫新、touchend代替click
4.HTML的viewport設(shè)置
5.開(kāi)啟GPU渲染加速
長(zhǎng)列表滾動(dòng)問(wèn)題,是移動(dòng)端需要面對(duì)的李剖,IOS盡量使用局部滾動(dòng)芒率,android盡量使用全局滾動(dòng)。同時(shí)篙顺,需要給body添加上-webkit-overflow-scrolling: touch來(lái)優(yōu)化移動(dòng)段的滾動(dòng)偶芍。
防抖和節(jié)流充择,設(shè)計(jì)到滾動(dòng)等會(huì)被頻繁觸發(fā)的DOM事件,需要做好防抖和節(jié)流的工作腋寨。它們都是為了限制函數(shù)的執(zhí)行頻次聪铺,以優(yōu)化函數(shù)觸發(fā)頻率過(guò)高導(dǎo)致的響應(yīng)速度跟不上觸發(fā)頻率,出現(xiàn)延遲萄窜,假死或卡頓的現(xiàn)象铃剔。
函數(shù)防抖:當(dāng)調(diào)用動(dòng)作過(guò)n毫秒后,才會(huì)執(zhí)行該動(dòng)作查刻,若在這n毫秒內(nèi)又調(diào)用此動(dòng)作則將重新計(jì)算執(zhí)行時(shí)間键兜;函數(shù)節(jié)流:預(yù)先設(shè)定一個(gè)執(zhí)行周期,當(dāng)調(diào)用動(dòng)作的時(shí)刻大于等于執(zhí)行周期則執(zhí)行該動(dòng)作穗泵,然后進(jìn)入下一個(gè)新周期普气。
touchstart、touchend代替click佃延,也是移動(dòng)端比較常用的操作现诀。click在移動(dòng)端會(huì)有300ms延時(shí),這種方法會(huì)影響用戶的體驗(yàn)履肃。所以做優(yōu)化時(shí)仔沿,最簡(jiǎn)單的方法就是使用touchstart或者touchend代替click。因?yàn)樗鼈兪录?zhí)行順序是touchstart->touchmove->touchend->click尺棋》怙保或者,使用fastclick或者zepto的tap事件代替click事件膘螟。
HTML的viewport設(shè)置成福,可以防止頁(yè)面的縮放,來(lái)優(yōu)化性能荆残。
開(kāi)啟GPU渲染加速奴艾,小伙伴們一定聽(tīng)過(guò)CPU吧,但是這里的GPU不能和CPU混為一談呦内斯。GPU的全名是Graphics Processing Unit握侧,是一種硬件加速方式。一般的css渲染嘿期,瀏覽器的渲染引擎都不會(huì)使用到它。但是埋合,在3D渲染時(shí)备徐,計(jì)算量較大,繁重甚颂,瀏覽器會(huì)開(kāi)啟顯卡的硬件加速來(lái)幫助完成這些操作蜜猾。所以秀菱,我們這里可以使用css中的translateZ設(shè)定,來(lái)欺騙瀏覽器蹭睡,讓其幫忙開(kāi)啟GPU加速衍菱,加快渲染進(jìn)程。
減少重定向
盡量避免使用重定向,當(dāng)頁(yè)面發(fā)生了重定向,就會(huì)延遲整個(gè)HTML文檔的傳輸造挽。在HTML文檔到達(dá)之前答恶,頁(yè)面中不會(huì)呈現(xiàn)任何東西,也沒(méi)有任何組件會(huì)被下載榨惰,降低了用戶體驗(yàn)
如果一定要使用重定向,如http重定向到https,要使用301永久重定向缕坎,而不是302臨時(shí)重定向。因?yàn)榇畚颍绻褂?02谜叹,則每一次訪問(wèn)http,都會(huì)被重定向到https的頁(yè)面搬葬。而永久重定向荷腊,在第一次從http重定向到https之后 ,每次訪問(wèn)http踩萎,會(huì)直接返回https的頁(yè)面
使用緩存
使用cach-control或expires這類強(qiáng)緩存時(shí)停局,緩存不過(guò)期的情況下,不向服務(wù)器發(fā)送請(qǐng)求香府。強(qiáng)緩存過(guò)期時(shí)董栽,會(huì)使用last-modified或etag這類協(xié)商緩存,向服務(wù)器發(fā)送請(qǐng)求企孩,如果資源沒(méi)有變化锭碳,則服務(wù)器返回304響應(yīng),瀏覽器繼續(xù)從本地緩存加載資源勿璃;如果資源更新了擒抛,則服務(wù)器將更新后的資源發(fā)送到瀏覽器,并返回200響應(yīng)
參考博客:
http://www.reibang.com/p/fe32ef31deed
https://www.cnblogs.com/huangyin1213/p/5853529.html
https://www.cnblogs.com/xiaohuochai/p/9178390.html