淺談網頁基本性能優化規則小結

這篇文章主要介紹了淺談網頁基本性能優化規則小結的相關資料,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

針對瀏覽器網頁的一些優化規則

頁面優化

靜態資源壓縮

藉助構建工具(webpack、gulp)適當壓縮圖片、腳本及樣式等網頁靜態資源。

CSS雪碧圖、base64內聯圖片

將站內小圖標合併成一張圖,使用css定位截取對應圖標;適當使用內聯圖片。

樣式置頂、腳本置底

頁面是一個逐步呈現的過程,樣式置頂能更快呈現頁面給用戶;<script> 標籤置頂會阻塞頁面後面資源的下載。

使用外鏈的css和js

多個頁面引用公共靜態資源,資源複用減少額外的http請求。

避免空src的圖片

避免不必要的http請求。

`<!-- 空src的圖片依然會發起http請求 -->`
`<``img` `src``=``""` `alt``=``"image"` `/>`

避免在html中縮放圖片

圖片儘量按需求使用指定規格的尺寸,而不是加載一張大圖片再將它縮小。

`<!-- 實際圖片尺寸爲600x300,在html中縮放爲了200x100 -->`
`<``img` `src``=``"/static/images/a.png"` `width``=``"200"` `height``=``"100"` `alt``=``"image"` `/>`

Preload預加載

給link標籤的rel設置preload屬性,可以讓瀏覽器在主渲染機制介入前就預加載資源。這種機制可以更早的獲取資源且不阻塞頁面的初始化。

`<!DOCTYPE html>`
`<``html` `lang``=``"en"``>`
`<``head``>`
`<``meta` `charset``=``"UTF-8"``>`
`<``title``>Document</``title``>`
`<``link` `ref``=``"preload"` `href``=``"style.css"` `as``=``"style"``>`
`<``link` `ref``=``"preload"` `href``=``"main.js"` `as``=``"script"``>`
`<``link` `ref``=``"stylesheet"` `href``=``"style.css"``>`
`</``head``>`
`<``body``>`
`<``script` `src``=``"main.js"``></``script``>`
`</``body``>`
`</``html``>`

例子中預加載了css和js文件,在之後的頁面渲染中,一旦使用它們就會立即調用。

可指定as的類型加載不同類型的資源。

  1. style
  2. script
  3. video
  4. audio
  5. image
  6. font
  7. document
  8. ...

該方式也可跨域預加載資源,設置crossorigin屬性即可。

`<``link` `rel``=``"preload"` `href``=``"fonts/cicle_fina-webfont.woff2"` `as``=``"font"` `type``=``"font/woff2"` `crossorigin``=``"anonymous"``>`

CSS

選擇器

選擇器的優先級從高到低排列爲:

  1. ID選擇器
  2. 類選擇器
  3. 標籤選擇器
  4. 相鄰選擇器

h``1 + p{ margin-top``: 15px``; }

選擇緊接在h1元素後出現的段落,h1和p元素擁有共同的父元素。

子選擇器

h``1 > strong {``color``:``red``;}

後代選擇器

h``1 em {``color``:``red``;}

通配符選擇器

屬性選擇器

`*[title] {``color``:``red``;}`
`img[alt] {``border``:` `5px` `solid` `red``;}`

僞類選擇器

選擇器使用經驗:

  1. 優先選擇類選擇器,可替代多層標籤選擇器;
  2. 慎用ID選擇器,雖然它效率高,但是在頁面中是唯一的,不利於團隊協作和維護;
  3. 合理利用選擇器的繼承性;
  4. 避免css表達式。

減少選擇器的層級

建立在上一條選擇器的優先級之上,應儘量避免多層次的選擇器嵌套,最好不要超過3層。

`.container .text .logo{` `color``:` `red``; }`
`/*改成*/`
`.container .text-logo{` `color``:` `red``; }`

精簡頁面樣式文件,去掉不用的樣式

瀏覽器會進行多餘的樣式匹配,影響渲染時間,另外樣式文件過大也會影響加載速度。

利用css繼承減少代碼量

利用css的可繼承屬性,父元素設置了樣式,子元素就不用再設置。

常見的可以繼承的屬性比如:color,font-size,font-family等;不可繼承的比如:position,display,float等。

屬性值爲0時,不加單位

css屬性值爲0時,可不加單位,減少代碼量。

`.text{` `width``:` `0px``;` `height``:` `0px``; }`
`/*改成*/`
`.text{` `width``:` `0``;` `height``:` `0``; }`

JavaScript

使用事件委託

給多個同類DOM元素綁定事件使用事件委託。

`<``ul` `id``=``"container"``>`
`<``li` `class``=``"list"``>1</``li``>`
`<``li` `class``=``"list"``>2</``li``>`
`<``li` `class``=``"list"``>3</``li``>`
`</``ul``>`
`// 不合理的方式:給每個元素都綁定click事件`
`$(``'#container .list'``).on(``'click'``,` `function``() {`
`var` `text = $(``this``).text();`
`console.log(text);`
`});`

// 事件委託方式:利用事件冒泡機制將事件統一委託給父元素

`$(``'#container'``).on(``'click'``,` `'.list'``,` `function``() {`
`var` `text = $(``this``).text();`
`console.log(text);   `
`});`

需要注意的是,雖然使用事件委託時都可以將事件委託給document來做,但這是不合理的,一個是容易造成事件誤判,另一個是作用域鏈查找效率低。應該選擇最近的父元素作爲委託對象。

使用事件委託除了性能上更優,動態創建的DOM元素也不需要再綁定事件。

DOMContentLoaded

可在DOM元素加載完畢(DOMContentLoaded)後開始處理DOM樹,不必等到所有圖片資源下載完後再處理。

`// 原生javascript`
`document.addEventListener(``"DOMContentLoaded"``,` `function``(event) {`
`console.log(``"DOM fully loaded and parsed"``);`
`},` `false``);`
`// jquery`
`$(document).ready(``function``() {`
`console.log(``"ready!"``);`
`});`
`// $(document).ready()的簡化版`
`$(``function``() {`
`console.log(``"ready!"``);`
`});`
      }//歡迎加入全棧開發交流划水交流圈:582735936
    ]//面向划水1-3年前端人員
  }   //幫助突破划水瓶頸,提升思維能力

預加載和懶加載

預加載

利用瀏覽器空閒時間預先加載將來可能會用到的資源,如圖片、樣式、腳本。

無條件預加載

一旦onload觸發,立即獲取將來需要用到的資源。

圖片資源預加載。(3種實現圖片預加載的方式)。

基於用戶行爲的預加載

對於用戶行爲可能進行的操作進行判斷,預先加載將來可能需要用到的資源。

  1. 當用戶在搜索輸入框輸入時,預先加載搜索結果頁可能用到的資源;
  2. 當用戶去操作一個Tab選項卡時,默認顯示其中一個,當要去點擊(click)其他選項時,在鼠標hover時,就可先加載將來會用到的資源;

懶加載

除頁面初始化需要的內容或組件之外,其他都可以延遲加載,如剪切圖片的js庫、不在可視範圍的圖片等等。

圖片懶加載。(判斷圖片是否在可視區域範圍內,若在,則將真實路徑賦給圖片)

避免全局查找

任何一個非局部變量在函數中被使用超過一次時,都應該將其存儲爲局部變量。

`function` `updateUI(){`
`var` `imgs = document.getElementsByTagName(``"img"``);`
`for` `(``var` `i=0, len=imgs.length; i < len; i++){`
`imgs[i].title = document.title +` `" image "` `+ i;`
`}`
`var` `msg = document.getElementById(``"msg"``);`
`msg.innerHTML =` `"Update complete."``;`
`}`

在上面函數中多次使用到document全局變量,尤其在for循環中。因此將document全局變量存儲爲局部變量再使用是更優的方案。

`function` `updateUI(){`
`var` `doc = document;`
`var` `imgs = doc.getElementsByTagName(``"img"``);`
`for` `(``var` `i=0, len=imgs.length; i < len; i++){`
`imgs[i].title = doc.title +` `" image "` `+ i;`
`}`
`var` `msg = doc.getElementById(``"msg"``);`
`msg.innerHTML =` `"Update complete."``;`
`}`
      }//歡迎加入全棧開發交流划水交流圈:582735936
    ]//面向划水1-3年前端人員
  }   //幫助突破划水瓶頸,提升思維能力

值得注意的一點是,在javascript代碼中,任何沒有使用var聲明的變量都會變爲全局變量,不正當的使用會帶來性能問題。

避免不必要的屬性查詢

使用變量和數組要比訪問對象上的屬性更有效率,因爲對象必須在原型鏈中對擁有該名稱的屬性進行搜索。

`// 使用數組`
`var` `values = [5, 10];`
`var` `sum = values[0] + values[1];`
`alert(sum);`
`// 使用對象`
`var` `values = { first: 5, second: 10};`
`var` `sum = values.first + values.second;`
`alert(sum);`

上面代碼中,使用對象屬性來計算。一次兩次的屬性查找不會造成性能問題,但若需要多次查找,如在循環中,就會影響性能。

在獲取單個值的多重屬性查找時,如:

var query = window.location.href.substring(window.location.href.indexOf(``"?"``));

應該減少不必要的屬性查找,將window.location.href緩存爲變量。

`var` `url = window.location.href;`
`var` `query = url.substring(url.indexOf(``"?"``));`

函數節流

假設有一個搜索框,給搜索框綁定onkeyup事件,這樣每次鼠標擡起都會發送請求。而使用節流函數,能保證用戶在輸入時的指定時間內的連續多次操作只觸發一次請求。

<``input type``=``"text" id``=``"input" value``=``"" />

`// 綁定事件`
`document.getElementById(``'input'``).addEventListener(``'keyup'``,` `function``() {`
`throttle(search);`
`},` `false``);`
`// 邏輯函數`
`function` `search() {`
`console.log(``'search...'``);`
`}`
`// 節流函數`
`function` `throttle(method, context) {`
`clearTimeout(method.tId);`
`method.tId = setTimeout(``function``() {`
`method.call(context);`
`}, 300);`
`}`

節流函數的應用場景不侷限搜索框,比如頁面的滾動onscroll,拉伸窗口onresize等都應該使用節流函數提升性能。

最小化語句數

語句數量的多少也是影響操作執行速度的因素。

將多個變量聲明合併爲一個變量聲明

`// 使用多個var聲明`
`var` `count = 5;`
`var` `color =` `"blue"``;`
`var` `values = [1,2,3];`
`var` `now =` `new` `Date();`
`// 改進後`
`var` `count = 5,`
`color =` `"blue"``,`
`values = [1,2,3],`
`now =` `new` `Date();`

改進的版本是隻使用一個var聲明,由逗號隔開。當變量很多時,只使用一個var聲明要比單個var分別聲明快很多。

使用數組和對象字面量

使用數組和對象字面量的方式代替逐條語句賦值的方式。

`var` `values =` `new` `Array();`
`values[0] = 123;`
`values[1] = 456;`
`values[2] = 789;`
`// 改進後`
`var` `values = [123, 456, 789];`
`var` `person =` `new` `Object();`
`person.name =` `"Jack"``;`
`person.age = 28;`
`person.sayName =` `function``(){`
`alert(``this``.name);`
`};`
`// 改進後`
`var` `person = {`
`name :` `"Jack"``,`
`age : 28,`
`sayName :` `function``(){`
`alert(``this``.name);`
`}`
`};`

字符串優化

字符串拼接

早期瀏覽器未對加號拼接字符串方式優化。由於字符串是不可變的,就意味着要使用中間字符串來存儲結果,因此頻繁的創建和銷燬字符串是導致它效率低下的原因。

`var` `text =` `"Hello"``;`
`text+=` `" "``;`
`text+=` `"World!"``;`

把字符串添加到數組中,再調用數組的join方法轉成字符串,就避免了使用加法運算符。

`var` `arr = [],`
`i = 0;`
`arr[i++] =` `"Hello"``;`
`arr[i++] =` `" "``;`
`arr[i++] =` `"World!"``;`
`var` `text = arr.join(``''``);`

現在的瀏覽器都對字符串加號拼接做了優化,所以在大多數情況下,加法運算符還是首選。

減少迴流和重繪

在瀏覽器渲染過程中,涉及到迴流和重繪,這是一個損耗性能的過程,應注意在腳本操作時減少會觸發迴流和重繪的動作。

  1. 迴流:元素的幾何屬性發生了變化,需要重新構建渲染樹。渲染樹發生變化的過程,就叫回流;
  2. 重繪:元素的幾何尺寸沒有變化,某個元素的CSS樣式(背景色或顏色)發生了變化。

觸發重排或重繪的操作有哪些?

  1. 調整窗口大小
  2. 修改字體
  3. 增加或者移除樣式表
  4. 內容變化,比如用戶在<input/>框中輸入文字
  5. 操作class屬性
  6. 腳本操作DOM(增加、刪除或修改DOM元素)
  7. 計算offsetWidth和offsetHeight屬性
  8. 設置style屬性的值

如何減少重排和重繪,提升網頁性能?

1、腳本操作DOM元素

  1. 將DOM元素設置爲display:none,設置過程中會觸發一次迴流,但之後可以隨意改動,修改完後再顯示;
  2. 將元素clone到內存中再進行操作,修改完後重新替換元素。

2、修改元素的樣式

  1. 儘量批量修改,而不是逐條修改;
  2. 預先設定好id、class,再設置元素的className。

3、爲元素添加動畫時將元素CSS樣式設爲position:fixed或position:absolute,元素脫離文檔流後不會引起迴流。

4、在調整窗口大小、輸入框輸入、頁面滾動等場景時使用節流函數(上面已提到過)。

HTTP

瀏覽器緩存

合理設置瀏覽器緩存是網頁優化的重要手段之一。

Expires 和 Cache-Control

Expires出自HTTP1.0,Cache-Control出自HTTP1.1,同時設置兩者時,Cache-Control 會覆蓋 Expires。

  1. Expires指定的是實際過期日期而不是秒數。但Expires存在一些問題,如服務器時間不同步或不準確。所以最好使用剩餘秒數而不是絕對時間來表達過期時間。
  2. Cache-Control可設置max-age值,單位秒,指定緩存過期時間。如:Cache-Control: max-age=3600。

ETag 和 Last-Modified

ETag 和 Last-Modified都由服務器返回在response headers中,其中ETag的優先級比Last-Modified高,也就是說服務器會優先判斷ETag的值。

  1. ETag是附加到文檔上的任意標籤,可能是文檔的序列號或版本號,或者是文檔內容的校驗等。當文檔改變時ETag值也會隨之改變。與ETag相關的是 If-None-Match,當瀏覽器發起請求時,會在If-None-Match字段攜帶ETag的值發給服務器;
  2. Last-Modified是文檔在服務器端最後被修改的時間。與Last-Modified相關的是If-Modified-Since,當瀏覽器發起請求時,會在If-Modified-Since字段攜帶Last-Modified的值發送給服務器。

強緩存和協商緩存

緩存的類型強緩存和協商緩存。兩者區別是,強緩存不會向服務器發請求,而協商緩存會發請求,匹配成功返回304 Not Modified,匹配不成功返回200;瀏覽器會先校驗強緩存,若強緩存未命中,再進行協商緩存校驗。

如何配置瀏覽器緩存

  1. 在web服務器的返回響應中添加Expires和Cache-Control;
  2. 在nginx或apache的配置文件中配置Expires和Cache-Control。

爲什麼要減少HTTP請求

在性能優化中減少http請求的措施佔了很大部分,比如:使用css雪碧圖代替多張圖片的請求、避免空src的圖片、使用內聯圖片、使用外鏈的css和js、緩存等。

從輸入URL到頁面加載完成的過程包括:

  1. DNS解析
  2. TCP連接
  3. HTTP請求與響應
  4. 瀏覽器渲染頁面
  5. 關閉連接

一個完整的http請求要經歷這些過程,它是耗時耗資源的,因此減少請求數就變得很有必要

本次給大家推薦一個免費的交流圈,裏面概括移動應用網站開發,css,html,webpack,vue node angular以及面試資源等。

對web開發技術感興趣的同學,歡迎加入,不管你是小白還是大牛我都歡迎,還有大牛整理的一套高效率學習路線和教程與您免費分享,同時每天更新視頻資料。

最後,祝大家早日學有所成,拿到滿意offer,快速升職加薪,走上人生巔峯。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章