vue前端性能優(yōu)化之預加載和懶加載示例詳解
預加載
預加載簡單來說就是將所有所需的資源提前請求加載到本地,這樣后面在需要用到時就直接從緩存取資源;我們使用該技術預先告知瀏覽器,等下某些資源可能要被使用,先把資源下載下來,不要等使用的時候再下載,可以看出這樣的加載技術會增加服務器的壓力,但是用戶的體驗會比較好,因為可以較快的看到后面的內容。
那看到這里很多問題的小明就說了,那預加載那么好用,以后我們就都用預加載了,服務器不是問題,一個字買;但如果在一個資源非常多,頁面非常長的電商網站場景中,如淘寶,我們要等待所有的資源都預加載完,再呈現給用戶么?那用戶估計會直接關閉淘寶打開京東;切記,任何一個技術都有它適用的場景和不適用的場景,我們要學會技術選型。
圖片預加載
HTML- img標簽
img標簽會在Html渲染解析到的時候,如果解析到img中src的值,則瀏覽器會立即開啟一個線程去請求該資源,所以我們可以先將img標簽隱藏但src寫上對應的鏈接,這樣皆可以把資源先請求回來了
// 預加載 <img src="https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg" style="display: none" />
Image對象
const image = new Image() image.src = "https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg"
只要瀏覽器把圖片下載到本地,同樣的src就會使用緩存,這是最基本也是最實用的預載方法;除了以上方法還有一些利用 XMLHttpRequest
對象或者第三庫如PerloadJS
庫來實現
JS預加載
js的加載方式
<script src="index.js"></script>
JS 會阻塞 dom 渲染,瀏覽器必須等待 index.js
加載和執(zhí)行完成后才能去做其它事情
<script async src="index.js"></script>
async模式下,它的加載時異步的,JS不會阻塞DOM渲染,async加載是無序的,當它加載完畢就會立即執(zhí)行;可以用于與DOM無關系的操作,比如埋點統(tǒng)計
<script defer src="index.js"></script>
defer 模式下,JS 的加載也是異步的,defer資源會在DOMConentLoaded
執(zhí)行之前,并且是有序的;如果多個script都設置了defer,會按引入順序執(zhí)行,如果需要控制資源加載順序時,可以使用這個模式,如 element-ui.js
依賴于 vue
,所以必須先引入vue.js
,再引入 element-ui.js
<script type="module">import { a } from './a.js'</script>
在主流的現代瀏覽器中,script 標簽的屬性可以加上 type="module"
,瀏覽器會對其內部的 import 引用發(fā)起 HTTP 請求,獲取模塊內容。這時 script 的行為會像是 defer 一樣,在后臺下載,并且等待 DOM 解析
<link rel="preload" as="script" href="index.js" rel="external nofollow" rel="external nofollow" >
link 標簽的 preload 屬性:用于提前加載一些需要的依賴,這些資源會優(yōu)先加載;vue2 項目打包生成的 index.html 文件,會自動給首頁所需要的資源,全部添加 preload,實現關鍵資源的提前加載
<link rel="prefetch" as="script" href="index.js" rel="external nofollow" rel="external nofollow" >
prefetch 是利用瀏覽器的空閑時間,加載頁面將來可能用到的資源的一種機制;通??梢杂糜诩虞d其他頁面(非首頁)所需要的資源,以便加快后續(xù)頁面的打開速度
async、defer 是 script 標簽的專屬屬性,對于網頁中的其他資源,可以通過 link 的 preload、prefetch 屬性來預加載如今現代框架已經將 preload、prefetch 添加到打包流程中了,通過靈活的配置,去使用這些預加載功能,同時我們也可以審時度勢地向 script 標簽添加 async、defer 屬性去處理資源,這樣可以顯著提升性能
preload
<!-- 使用 link 標簽靜態(tài)標記需要預加載的資源 --> <link rel="preload" href="/path/to/style.css" rel="external nofollow" as="style"> ? <!-- 或使用腳本動態(tài)創(chuàng)建一個 link 標簽后插入到 head 頭部 --> <script> const link = document.createElement('link'); link.rel = 'preload'; link.as = 'style'; link.href = '/path/to/style.css'; document.head.appendChild(link); </script>
preload
提供了一種聲明式的命令,能讓瀏覽器提前加載指定資源(如腳本或者樣式表),并在需要執(zhí)行的時候再執(zhí)行。這在希望加快某個資源的加載速度時很有用。在 preload
下載完資源后,資源只是被緩存起來,瀏覽器不會對其執(zhí)行任何操作。不執(zhí)行腳本,不應用樣式表。
注意:設置了 rel
屬性的 link
標簽 必須設置 as
屬性來聲明資源的類型,否則瀏覽器可能無法正確加載資源。常見的 as
屬性包括:
script
: JavaScript 文件style
: CSS 樣式文件font
: 字體文件image
: 圖片文件fetch
: 通過fetch
或者XHR
獲取的文件,例如ArrayBuffer
或者JSON
文件。
prefetch
<link rel="prefetch" href="static/img/delay_load_img.a5bb7c33.png" rel="external nofollow" >
prefetch
(鏈接預?。┦且环N瀏覽器機制,其利用瀏覽器空閑時間來下載或預取用戶在不久的將來可能訪問的文檔。網頁向瀏覽器提供一組預取提示,并在瀏覽器完成當前頁面的加載后開始靜默地拉取指定的文檔并將其存儲在緩存中。當用戶訪問其中一個預取文檔時,便可以快速的從瀏覽器緩存中得到。prefetch
是一個低優(yōu)先級的資源提示,允許瀏覽器在后臺空閑時獲將來可能用得到的資源,并且將他們存儲在瀏覽器的緩存中。一旦一個頁面加載完畢就會開始下載其他的資源,然后當用戶點擊了一個帶有 prefetched 的連接,它將可以立刻從緩存中加載內容。
Preload & Prefetch 的區(qū)別
preload
的設計初衷是為了盡早加載首屏需要的關鍵資源,從而提升頁面渲染性能;preload 是告訴瀏覽器頁面必定需要的資源,瀏覽器一定會加載這些資源prefetch
聲明的是將來可能訪問的資源,因此適合對異步加載的模塊、可能跳轉到的其他路由頁面進行資源緩存,瀏覽器不一定會加載這些資源- 大部分場景下無需特意使用
preload
;類似字體文件這種隱藏在腳本、樣式中的首屏關鍵資源,建議使用preload
; - 異步加載的模塊(典型的如單頁系統(tǒng)中的非首頁)建議使用
prefetch
,大概率即將被訪問到的資源可以使用prefetch
提升性能和體驗 - 注:preload 和 prefetch 混用的話,并不會復用資源,而是會重復加載。
不同資源加載的優(yōu)先級規(guī)則
DevTools Priority 體現的優(yōu)先級,一共分成五個級別:
- Highest 最高
- Hight 高
- Medium 中等
- Low 低
- Lowest 最低
其中
- html 主要資源,其優(yōu)先級是最高的
- css 樣式資源,其優(yōu)先級也是最高的
- script 腳本資源,優(yōu)先級不一
- font 字體資源,優(yōu)先級不一
懶加載
懶加載也叫延遲加載;頁面加載速度快、可以減輕服務器的壓力、節(jié)約了流量,用戶體驗好;
懶加載的幾種實現方式
- 純粹的延遲加載,使用setTimeOut或setInterval進行加載延遲.
- 條件加載,符合某些條件,或觸發(fā)了某些事件才開始異步下載
- 可視區(qū)加載,即僅加載用戶可以看到的區(qū)域,這個主要由監(jiān)控滾動條來實現
圖片懶加載
對于一些圖片比較多的頁面,用戶打開頁面后,只需要呈現出在屏幕可視區(qū)域內的圖片,當用戶滑動頁面時,再去加載出現在屏幕內的圖片,以優(yōu)化頁面的加載效果;
實現:頁面中的img元素,如果沒有src屬性,瀏覽器就不會發(fā)出請求去下載圖片,只有通過javascript設置了圖片路徑,瀏覽器才會發(fā)送請求。懶加載的原理就是先在頁面中把所有的圖片統(tǒng)一使用一張占位圖進行占位,把正真的路徑存在元素的“data-url”(這個名字起個自己認識好記的就行)屬性里,要用的時候就取出來,再設置。
獲取屏幕可視窗口大小的幾種方法
window.innerHeight // 標準瀏覽器及IE9+ document.documentElement.clientHeight // 標準瀏覽器及低版本IE標準模式 document.body.clientHeight // 低版本混雜模式
獲取瀏覽器窗口頂部與文檔頂部之間的距離,即滾動條滾動的距離
window.pagYoffset // 標準瀏覽器及IE9+ document.documentElement.scrollTop // 兼容ie低版本的標準模式 document.body.scrollTop // 兼容混雜模式;
路由懶加載
在SPA應用中,一個路由對應一個頁面,如果我們不做任何處理,項目打包時,所有的頁面都會打包成一個文件,當用戶去打開首頁時,就會去一次性加載所有的資源,這樣首頁加載就會慢,降低用戶體驗,那有什么辦法不一次性加載所有資源?是用什么原理實現的?
在ES6中,有一個動態(tài)加載模塊的方法:import();懶加載就是根據import()去實現的,調用import()之處,被作為分離模塊的起點,意思是,被請求的模塊和它引用的所有子模塊,會被分離到一個單獨chunk中;所以實現懶加載的方法,就是將需要進行懶加載的子模塊分離出來,打包成一個單獨的文件,這樣就不會一次加載所有的資源了;
// 通過webpackChunkName設置分割后代碼塊的名字 const Home = () => import(/* webpackChunkName: "home" */ "@/views/home/index.vue"); const MetricGroup = () => import(/* webpackChunkName: "metricGroup" */ "@/views/metricGroup/index.vue"); ? const routes = [ { path: "/", name: "home", component: Home }, { path: "/metricGroup", name: "metricGroup", component: MetricGroup }, ]
注:webpackChunkName 作用是 webpack 在打包的時候,對異步引入的庫代碼(lodash)進行代碼分割時,設置代碼塊的名字。webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中
組件懶加載
這個實現原理和路由懶加載是一樣的,都是通過import()的方式實現的,那組件懶加載什么時候用呢?
假設有兩個復雜頁面都使用到了同一個組件,項目打包后,發(fā)現兩個頁面均包括了該組件的代碼;且該組件又不是一進入頁面就觸發(fā)的,需要一定條件才觸發(fā)的;這個時候就比較適合使用組件懶加載;即組件懶加載的使用場景有:
- 該頁面文件體積大,導致頁面打開慢,可以通過懶加載進行資源拆分,利用瀏覽器的并行下載提升速度
- 該組件又不是一進入頁面就觸發(fā)的,需要一定條件才觸發(fā)的(比如彈窗)
- 該組件復用性高,很多頁面引用,可以理由懶加載單獨形成一個文件
其他時候不建議拆分過細,因為會造成瀏覽器http請求增多;
最后
預加載和懶加載都有各自的優(yōu)缺點,我們要根據不同的情況選擇不同的技術去解決問題。
以上就是vue前端性能優(yōu)化之預加載和懶加載示例詳解的詳細內容,更多關于vue前端預加載懶加載的資料請關注腳本之家其它相關文章!
相關文章
從Echarts報錯中學習Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo
這篇文章主要介紹了從Echarts報錯中學習Vue3?ref和shallowRef區(qū)別及其組件二次封裝demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11vue3使用el-radio-group獲取表格數據無法選中問題及解決方法
這篇文章主要介紹了vue3使用el-radio-group獲取表格數據無法選中問題及解決方法,本文給大家介紹的非常詳細,需要的朋友可以參考下2024-05-05vue路由history模式頁面刷新404解決方法Koa?Express
這篇文章主要為大家介紹了vue路由history模式頁面刷新404解決方法(Koa?Express)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11