使用Page Visibility API來提升頁面性能和用戶體驗

這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰html

前言

Chrome中,每個網頁標籤都是一個進程,當該標籤處於不可見狀態必定時間後會處於休眠狀態以節省內存等系統資源。咱們在開發時候有時須要檢測用戶是否處於當前頁面,以知足功能上的需求。html5

在以往,判斷用戶是否處於當前頁面,一般是判斷pagehidebeforeunloadunload這三個事件,可是在移動端上不必定所有都會觸發,由於當前頁面被系統切換到另一個應用,以及系統殺死瀏覽器進程,是沒法監聽到的。當用戶切換應用,而後因爲內存不足或過久未使用,系統會直接殺死瀏覽器進程,此時unloadbeforeunload會來不及觸發。webpack

Page Visibility API,無論移動端仍是桌面,全部狀況下,都能監聽到頁面的可見性發生變化。使用它能夠加強用戶體驗,當用戶不在當前頁面時,能夠中止音視頻播放,網絡請求,動畫加載等,以節約資源和電量。web

接口特性

Page Visibility API的方法和屬性被掛載到document對象上,咱們隨時都能調用它,它具備如下屬性:api

  • document.hidden:窗口是否不可見,只讀屬性,當窗口處於徹底不可見時爲true
  • document.visibilityState:只讀屬性,表示當前窗口的狀態: 'hidden' | 'visible' | 'prerender',只要當前頁面有一丁點可見都爲true
  • visibilitychange:事件類型,當窗口的可見性發生變化時觸發。

推薦使用document.visibilityState而不是document.hidden,它除了能檢測頁面的可見性還能檢測頁面是否處於預渲染階段。瀏覽器

document.hidden

只讀屬性,返回一個布爾值,表示頁面是否可見,爲true時表示徹底不可見。緩存

document.visibilityState

相對於document.hiddendocument.visibilityState能檢測更復雜的場景。它有三個狀態值:markdown

  • hidden:頁面徹底不可見。
  • visible:頁面至少一部分可見。
  • prerender:頁面即將或正在渲染,處於不可見狀態。

prerender狀態只在支持"預渲染"的瀏覽器上纔會出現,好比 Chrome 就有預渲染功能,能夠在用戶不可見的狀態下,預先把頁面渲染出來,等到用戶要瀏覽的時候,直接展現渲染好的網頁。網絡

如下狀況爲hidden:app

  • 瀏覽器最小化。
  • 瀏覽器沒有最小化,可是當前頁面切換爲其餘頁面。
  • 瀏覽器將要卸載(unload)頁面。
  • 系統鎖屏。

上面四種場景涵蓋了頁面可能被卸載的全部狀況。除了hiddenprerender,其餘時候只要有一點頁面顯示都爲visible

頁面卸載以前,document.visibilityState必定會變成hidden狀態,這也是W3C設計這個API的主要目的。

visibilitychange

只要document.visibilityState屬性發生變化,就會觸發visibilitychange事件。所以,能夠經過監聽這個事件來檢測頁面可見性的變化。

document.addEventListener("visibilitychange",()=>{
   if(document.visibilityState==="hidden"){
       console.log("頁面不可見")
   }
   else{
       console.log("頁面可見")
   }
})
複製代碼

document.visibilityState屬性只針對頂層窗口,內嵌的<iframe>頁面的document.visibilityState屬性由頂層窗口決定。使用 CSS 屬性隱藏<iframe>頁面(好比display: none;),並不會影響內嵌頁面的可見性。

MDN的描述:

<iframe>的可見性狀態與父文檔相同。使用CSS屬性(例如display: none;)隱藏<iframe>不會觸發可見性事件或更改框架中包含的文檔的狀態。

使用場景

節省音頻流量

當用戶離開當前頁面時,咱們能夠暫停音視頻的播放,以節省用戶的流量。

<video id="video">
  <source id='mp4' src="movie.mp4" type='video/mp4'/>
</video>
複製代碼
const onVisibilityChange = () => {
  const video = document.getElementById("video");
  // 頁面徹底不可見時,暫停播放,可見時則恢復播放
  return document.hidden
    ? video.pause()
    : video.play();
}

document.addEventListener("visibilitychange", onVisibilityChange);
複製代碼

一個栗子: Demo: Page Visibility API (daniemon.com)

資源懶加載

除了節省流量,咱們也能夠結合webpack的動態加載模塊import()實現資源的懶加載。例如,當用戶離開當前頁面,咱們能夠請求用戶接下來可能用到的資源並緩存起來,以提升使用體驗。

let loaded = false;
const onVisibilityChange = () => {
  if (!loaded && document.visibilityState === 'visible') {
    Promise.all([
      import(/* webpackChunkName: "bundle-[index]"*/ './dist'),
      import(/* webpackPrefetch: 0 */ './images')
    ]).then(() => {
      loaded = true;
    });
  }
};

document.addEventListener('visibilitychange', onVisibilityChange);
複製代碼

其餘

除了上面提到的場景外,咱們還能用來關閉定時器,掛起webSocket輪詢,中止頁面動畫特效等等,這些都能進一步提升頁面的性能和用戶體驗。

總結

image.png

目前該接口獲得普遍的支持,web性能工做組織Web Performance Working Group)也提倡咱們在構建應用時使用該API來提高提高應用性能和用戶體驗。

參考

往期文章

相關文章
相關標籤/搜索