項目中資源緩存機制實踐(靜態資源和本地數據緩存)

網絡資源的緩存

核心方案

  1. HTML文件 no-cache
  2. js,css文件 時間戳/哈希/版本號,長緩存
  3. 圖片資源 長緩存,更新時使用新鏈接地址
1. 前後端未分離,且未引入構建工具的項目

方案:每次上線時,維護一個版本記錄,由後端給每個頁面上提供當前的版本號,前端在引用js和css時將版本號放在資源的query參數中。

例如:

原先:
<script src="/static/js/utils.js"></script>
<script src="/static/js/index.js"></script>

改後:
// 每次發版維護的版本號
const version = '2.2';
// 動態填寫js引用
document.write("<script type='text/javascript' src=./utils.js?version="+ version + "><\/script>"); 

2. 使用構建工具的項目

方案:使用webpack和grunt之類的工具,每次發版時使用工具使用hash更新靜態資源的版本

例如:

<script src="/static/js/0.2e29befc85b7d79378f4.js"></script>

本地緩存的管理

cookie、localStorage、sessionStorage、IndexDB、App cache、service worker
使用本地存儲的注意點:
  1. 使用要有節制,同一個域名下共享localstorage空間,如果一個域名下的業務非常多,很可能存儲量超過限制。像我們的不同業務域名時projectA.XXX.com, projectB.XXX.com 而不是www.XXX.com/projectA, www.XXX.com/projectB。使用子域名可以分離storage空間,互不干擾。
  2. 使用要有降級方案,不能完全依賴storge完成業務功能。如果storage讀寫失敗,使用備用方案。
  3. 使用時要有版本管理。storage中儲存的key也要有版本管理,便於迭代時避免不同版本之間數據衝突。 V1.0.0_XXXX

下面寫了一個用於本地存取的工具,項目中使用時可以將工具綁定到全局空間中使用。例如在Vue生態中,可以結合Vux一起使用

const namespace = 'matchu'
const version = '2.2'

function setLocal(key, value, priority) {
  try {
    // 設置的優先級不合法,爲非數字時,使用最低優先級0
    priority = /^[0-9]\d*$/.test(priority) ? priority : 0
    localStorage.setItem(`${namespace}_V:${version}_P:${priority}`, JSON.stringify(value))
    return getLocal(key)
  } catch (err) {
    if (/exceeded the quota/.test(err)) {
      // 存儲超出限額, 清除低優先級的數據
      clearLowPriorityLocal(priority)
    }
  }
}

function getLocal(key, value) {
  try {
    let result = localStorage.getItem(key)
    // 讀取成功立即返回值
    // 讀取失敗則嘗試先存儲數據,再返回已存入的數據
    result = result ? JSON.parse(result) : setLocal(key, value)
    return result
  } catch (err) {
    // 讀取失敗
    console.log(err)
  }
}

// 刪除指定key數據
function removeLocal(key) {
  try {
    localStorage.removeItem(key)
  } catch (err) {
    // 清除所有數據失敗
    console.log(err)
  }
}

// 刪除所有數據
function clearAllLocal() {
  try {
    localStorage.clear()
  } catch (err) {
    // 清除所有數據失敗
    console.log(err)
  }
}

// 正則匹配刪除當前命名空間且非當前版本的數據
function clearOtherVersionLocal() {
  try {
    const reg = new RegExp(`^${namespace}_V:(?!${version})`)
    Object.keys(localStorage).forEach(key => {
      if (reg.test(key)) {
        removeLocal(key)
      }
    })
  } catch (err) {
    console.log(err)
  }
}

// 正則匹配刪除低於當前優先級的數據
function clearLowPriorityLocal(priority) {
  try {
    const reg = new RegExp(`[^${namespace}_V:${version}_P:]`)
    Object.keys(localStorage).forEach(key => {
      const index = key.match(reg).index
      if (index && key.slice(index) < priority) {
        removeLocal(key)
      }
    })
  } catch (err) {
    console.log(err)
  }
}
export default {
  setLocal: setLocal, // 存storage數據
  getLocal: getLocal, // 取storage
  removeLocal: removeLocal, //刪除指定key的數據
  clearAllLocal: clearAllLocal, // 刪除全部數據
  clearOtherVersionLocal: clearOtherVersionLocal, // 清除非本次版本的數據
  clearLowPriorityLocal: clearLowPriorityLocal // 清除低於當前優先級的數據
}

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