摘要:之離線存儲離線存儲顧名思義,在有線的環境下先緩存數據包括靜態資源,動態資源,從而在離線環境下,依舊可以正常使用應用單頁應用靜態資源存儲是一套靜態資源緩存方案利用該技術可以實現配置靜態資源轉發請求,加快應用加載速度,降低服務器負載基本用法引入
H5之「離線存儲」
「離線存儲」:顧名思義,在有線的環境下先緩存數據(包括靜態資源,動態資源),從而在離線環境下,依舊可以正常使用應用(單頁應用)
靜態資源存儲(ApplicationCache)applicationCache 是一套h5靜態資源緩存方案.
利用該技術可以實現配置靜態資源/轉發請求,加快應用加載速度,降低服務器負載.
引入manifest配置文件
... ...
配置manifest文件
CACHE MANIFEST # 修改配置后,附加上下面一段js代碼,才能更新緩存 # 2016972143 # 注釋:需要緩存的文件,無論在線與否,均從緩存里讀取 CACHE: /dist/0.eda078350ef514670764.bundle.js /dist/common.bundle.js?v=2016972143 /dist/df9f379beae2559b27044dcfdc0653ab.png?v=2016972143 /dist/home.bundle.js?v=2016972143 /dist/home.css?v=2016972143 uncached.js?v=2016972143 #cached.css # 注釋:不緩存的文件,無論緩存中存在與否,均從新獲取 NETWORK: * #uncached.js #uncached.css # 注釋:獲取不到資源時的備選路徑,如index.html訪問失敗,則返回404頁面 FALLBACK: #/v1/team/dirlists mock/team_dirlists.json #/v1/team/app_filelist?isAdd=0&source=team&page=1&pageSize=10&sort=ftime&from=hiwebapp&fid=t293 mock/team_app_filelist.json #index.html 404.html
書寫更新緩沖js
// 每次打開頁面執行該代碼段,更新緩存 // !!! 注意:更新緩存后不會立即生效,需要重新加載頁面 (function () { var cache = window.applicationCache; cache.addEventListener("updateready", function(e) { if (cache.status == cache.UPDATEREADY) { // Browser downloaded a new app cache. // if (confirm("A new version of this site is available. Load it?")) { cache.swapCache(); window.location.reload(); // } } else { // Manifest didn"t changed. Nothing new to server. } }, false); cache.update() }())
服務器配置
配置manifest文件,響應 Content-Type: text/cache-manifest Cache-Control: max-age=0
部署線上代碼時更新manifest版本號與配置
按照以上配置,這樣就能實現靜態資源緩存
如上圖,from cache的加載時間相比其他網絡請求快得多!
其中的fetch/ajax請求不能夠通過靜態資源存儲,因為響應結果是可能會變的.
那么對于異步ajax請求(動態資源)要通過什么方法才能存儲起來呢?實現真正意義的離線存儲.
動態資源存儲(WebSQL/IndexedDB)使用前端數據庫可以較為靈活的控制動態資源存儲,在這里我使用了indexedDB, 為什么不用WebSQL?
之前做在線聊天應用時,使用過WebSQL存儲聊天記錄
WebSQL已經被棄用
WebSQL是傳統的關系數據庫,indexedDB是主流的NoSQL DB
基本用法創建一個通用的數據庫訪問接口
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB; // memCache 內存緩沖,避免頻繁的讀寫數據庫 var req, db, memCache = {}; if(indexedDB) { // version:2 req = indexedDB.open("ajax_cache", 2); // 保證caches成功創建 req.onsuccess = function (e) { db = e.target.result; if(!db.objectStoreNames.contains("caches")){ db.createObjectStore("caches", {keyPath: "id"}); } } // 數據庫版本改變觸發 req.onupgradeneeded=function(e){ var db=e.target.result; if(!db.objectStoreNames.contains("caches")){ db.createObjectStore("caches", {keyPath: "id"}); } console.log("DB version changed to " + db.version); }; req.onerror = function (err) { console.error("indexedDB open failed. ", err) } } export default { isSupported: !!indexedDB, set: (id, data) => { var entity = { id: id, data: data } var transaction = db.transaction("caches", "readwrite"); var store = transaction.objectStore("caches"); var req = store.put(entity); req.onerror = () => { console.error("put data failed. ", entity) } req.onsuccess = () => { memCache[id] = data console.info("put data successed. ", entity) } }, get: (id) => { return new Promise((resolve, reject) => { if(memCache[id]) { resolve(memCache[id]); return; } var transaction = db.transaction("caches", "readwrite"); var store = transaction.objectStore("caches"); var req = store.get(id); req.onerror = () => { console.error("get data failed. ", id) resolve() } req.onsuccess = (e) => { var rlt = e.target.result; console.info("get data successed. ", id, rlt) resolve(rlt && rlt.data) } }) } }
重寫fetch/ajax方法
/* reset fetch function for offline be compatible*/ var fetch = require("isomorphic-fetch") import {parse} from "url" var __fetch = fetch; fetch = function (url) { var rlt = parse(url, true); function generateJson(json) { return { json: function () { return json } } } function generateErrorJson() { return generateJson({ errno: 500, errmsg: "你正處于離線狀態", result: { files: [] } }) } var query = rlt.query; // 去掉時間戳與重復的from參數 delete query.t; delete query.from; var id = rlt.pathname var key = MyUtils.jsonToUrl(query) if(MyUtils.isOffline()) { // 離線 if(!id) { return new Promise((resolve, reject) => { resolve(generateErrorJson()) }) } else { if(DB.isSupported) { return DB.get(id).then(json => { return (!json || !json[key]) ? generateErrorJson() : generateJson(json[key]) }) } else { return new Promise((resolve, reject) => { resolve(generateErrorJson()) }) } } } else { return __fetch.apply(null, [].slice.call(arguments)) .then(res => res.json()) .then( (resJson) => { if(DB.isSupported) { var tmp = {}; tmp[key] = resJson; DB.get(id).then(json => { DB.set(id, Object.assign({}, json, tmp)) }) } return generateJson(resJson) } ) } }
可以在chrome的web tool中看到indexedDB
每次請求都緩存下來了
在脫離網絡后!依舊可以模擬異步請求!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/61810.html
摘要:本文將從以下幾個方面闡述架構設計的一些經驗和思考。原文及討論請到通訊作為一種跨語言開發模式,通訊層是架構首先應該考慮和設計的,往后所有的邏輯都是基于通訊層展開。 關于Hybrid模式開發app的好處,網絡上已有很多文章闡述了,這里不展開。 本文將從以下幾個方面闡述Hybrid app架構設計的一些經驗和思考。 原文及討論請到 github issue 通訊 作為一種跨語言開發模式,通訊...
摘要:前端面試題總結持續更新中為什么只需要寫需要來規范瀏覽器的行為讓瀏覽器按照它們應該的方式來運行基于所以需要對進行引用,才能告知瀏覽器文檔所使用的文檔類型。 前端面試題總結——H5(持續更新中) 1.HTML5 為什么只需要寫 ? HTML5 需要doctype來規范瀏覽器的行為,讓瀏覽器按照它們應該的方式來運行; HTML4.01基于SGML,所以需要對DTD進行引用,才能告知瀏覽器文檔...
閱讀 1839·2021-09-22 15:23
閱讀 3268·2021-09-04 16:45
閱讀 1873·2021-07-29 14:49
閱讀 2773·2019-08-30 15:44
閱讀 1524·2019-08-29 16:36
閱讀 1042·2019-08-29 11:03
閱讀 1510·2019-08-26 13:53
閱讀 509·2019-08-26 11:57