今天小編為大家?guī)?lái)一個(gè)有關(guān)于:“在HTML5實(shí)現(xiàn)應(yīng)用程序緩存(Application Cache)的方法分享!”這方面的相關(guān)內(nèi)容分享,希望對(duì)小伙伴們有所幫助!
為什么要使用Application Cache技術(shù)?
在HTML5之前,我們需要接入網(wǎng)絡(luò)才能訪問(wèn),這毫無(wú)疑問(wèn)是網(wǎng)站多次請(qǐng)求服務(wù)器,造成速度變慢,對(duì)于PC用戶(hù),網(wǎng)絡(luò)相對(duì)比較穩(wěn)定,載入速度也不會(huì)差太多。但是移動(dòng)端呢?移動(dòng)端依賴(lài)無(wú)線信號(hào)、依賴(lài)信號(hào)塔、位置不固定、受附近建筑影響等。一系列導(dǎo)致網(wǎng)絡(luò)的不穩(wěn)定,我們不能改變用戶(hù),也不能放棄網(wǎng)絡(luò)較慢的用戶(hù)。
還有,在混合app領(lǐng)域,經(jīng)常使用內(nèi)置webview加載html頁(yè)面,如果網(wǎng)速太慢,依然會(huì)造成上述問(wèn)題。
離線存儲(chǔ)技術(shù)
實(shí)際開(kāi)發(fā)中,主要是使用Application Cache和LocalStorage技術(shù),它們來(lái)自HTML5技術(shù)。
(1)Application Cache:通常用于靜態(tài)資源(靜態(tài)頁(yè)面)的緩存。
(2)LocalStorage:通常用于AJAX請(qǐng)求緩存,存儲(chǔ)非關(guān)鍵性AJAX數(shù)據(jù)。
我用一段話(huà)來(lái)贅述下為什么要使用Application Cache技術(shù):
當(dāng)頁(yè)面有些元素它們是不變的,你可以使用Application Cache技術(shù)離線緩存掉,每次訪問(wèn)這些緩存掉的元素就不需要再請(qǐng)求服務(wù)器了,當(dāng)有些東西經(jīng)常變,那就讓它們每次請(qǐng)求服務(wù)器吧!
HTML5 Application Cache特性
HTML5 引入了應(yīng)用程序緩存,這意味著 web 應(yīng)用可進(jìn)行緩存,并可在沒(méi)有因特網(wǎng)連接時(shí)進(jìn)行訪問(wèn)。
應(yīng)用程序緩存為應(yīng)用帶來(lái)三個(gè)優(yōu)勢(shì):
(1)離線瀏覽:用戶(hù)可在不介入網(wǎng)絡(luò)時(shí)訪問(wèn)使用
(2)速度提升:已緩存資源加載得更快
(3)減少對(duì)服務(wù)器的請(qǐng)求:瀏覽器將只從服務(wù)器下載更新過(guò)或更改過(guò)的資源
支持情況:除了IE瀏覽器,都支持Application Cache
開(kāi)始使用Application Cache
涉及角色:服務(wù)器和html文件
服務(wù)器端需要做的事情
管理維護(hù)manifest.appcache文件,檢查manifest清單中是否有無(wú)法訪問(wèn)的文件,并及時(shí)更新,以免造成損失。
manifest文件(W3C建議文件擴(kuò)展名為.appcache)
manifest 文件是簡(jiǎn)單的文本文件,它告知瀏覽器被緩存的內(nèi)容(以及不緩存的內(nèi)容)。
manifest 文件可分為三個(gè)部分:
- CACHE MANIFEST - 在此標(biāo)題下列出的文件將在首次下載后進(jìn)行緩存
- NETWORK - 在此標(biāo)題下列出的文件需要與服務(wù)器的連接,且不會(huì)被緩存
- FALLBACK - 在此標(biāo)題下列出的文件規(guī)定當(dāng)頁(yè)面無(wú)法訪問(wèn)時(shí)的回退頁(yè)面(比如 404 頁(yè)面)
我們梳理一下逐一進(jìn)行介紹
一、CACHE MANIFEST(它是必須的)
CACHE MANIFEST
/reset.css
/logo.gif
/hx.js
manifest 文件列出了三個(gè)資源:一個(gè) CSS 文件,一個(gè) GIF 圖像,以及一個(gè) JavaScript 文件。當(dāng) manifest 文件加載后,瀏覽器會(huì)從網(wǎng)站的根目錄下載這三個(gè)文件。然后,無(wú)論用戶(hù)何時(shí)與因特網(wǎng)斷開(kāi)連接,這些資源依然是可用的。
注意:文件位置根據(jù)文件在服務(wù)器的實(shí)際目錄,確保路徑正確。
總結(jié):CACHE MANIFEST列出的資源是需要在本地緩存的文件(要緩存的文件)
二、NETWORK
NETWORK: nav.html
NETWORK 小節(jié)規(guī)定文件 “nav.html” 永遠(yuǎn)不會(huì)被緩存,且離線時(shí)不可用。
NETWORK: *
也可以使用星號(hào)“ * ”來(lái)指示所有其他資源/文件都需要因特網(wǎng)連接。
注意:千萬(wàn)不要把首頁(yè)index放入NETWORK中禁止緩存,否則插件等無(wú)法使用。
總結(jié):NETWORD列出的資源是需要每次請(qǐng)求的動(dòng)態(tài)資源文件(不緩存的文件)
三、FALLBACK
FALLBACK: /index/ /404.html
FALLBACK 小節(jié)規(guī)定如果無(wú)法建立因特網(wǎng)連接,則用 “404.html” 替代 /index/ 目錄中的所有文件。
注意:第一個(gè) URI 是資源,第二個(gè)是替補(bǔ)。
總結(jié):FALLBACK列出的資源是如果某個(gè)文件無(wú)法聯(lián)網(wǎng)或接入失敗,則使用后一個(gè)替補(bǔ)顯示。(友好的替補(bǔ)頁(yè)面)
完整的manifest文件:
CACHE MANIFEST # Files that need to be cached2014.6.5 /reset.css /logo.gif /hx.js NETWORK: #Files that do not need caching2014.6.5 nav.html FALLBACK: #Files to be replaced2014.6.5 /index/ /404.html
注意:#代表注釋行,看似簡(jiǎn)單的注釋行卻有著很大的用處,為什么這么說(shuō)呢,因?yàn)閼?yīng)用的緩存會(huì)在其 manifest 文件更改時(shí)被更新。如果您編輯了一幅圖片,或者修改了一個(gè) JavaScript 函數(shù),這些改變都不會(huì)被重新緩存。更新注釋行中的日期和版本號(hào)、時(shí)間戮或md5碼等,是一種使瀏覽器重新緩存文件的辦法。
html需要做的事情
只需要引入manifest.appcache文件:
<!DOCTYPE HTML>
<html manifest="manifest.appcache">
Application Cache生命銷(xiāo)毀規(guī)則
(1)用戶(hù)清空瀏覽器的緩存,此時(shí)Application Cache本地緩存將銷(xiāo)毀。
(2)manifest文件被修改時(shí),因?yàn)閼?yīng)用的緩存會(huì)在其 manifest 文件更改時(shí)被更新。如果您編輯了一幅圖片,或者修改了一個(gè) JavaScript 函數(shù),這些改變都不會(huì)被重新緩存,此時(shí)Application Cache本地緩存將銷(xiāo)毀。
(3)由程序來(lái)更新應(yīng)用緩存
深入manifest.appcache文件
首先提醒的就是,千萬(wàn)不要把index首頁(yè)禁止緩存,雖然放入NETWORK也不起作用,這是一種規(guī)范,也是一種規(guī)則,請(qǐng)遵守。
HTTP相關(guān)的緩存頭域以及https的緩存頁(yè)面限制,將被manifest所無(wú)視,所以在用戶(hù)代理更新頁(yè)面之前,它是不會(huì)過(guò)期的,也就是說(shuō),即使是HTTPS,也可以脫機(jī)工作。
各大瀏覽器對(duì)應(yīng)用緩存的容量限制有所不同,幾乎為5MB。
當(dāng)一個(gè)資源被緩存后,該瀏覽器直接請(qǐng)求這個(gè)絕對(duì)路徑也會(huì)訪問(wèn)緩存中的資源。
緩存包含manifest清單的頁(yè)面,所以實(shí)際上,即使我們不顯示的把包含manifest的頁(yè)面,列在manifest緩存清單中,這個(gè)頁(yè)面也會(huì)被緩存。
每次網(wǎng)站更新,服務(wù)器端要進(jìn)行manifest.appcache文件的檢查和更新,避免造成損失。
站點(diǎn)中的其他頁(yè)面即使沒(méi)有設(shè)置manifest屬性,請(qǐng)求的資源如果在緩存中也從緩存中訪問(wèn)。
如果manifest文件,或者內(nèi)部列舉的某一個(gè)文件不能正常下載,整個(gè)更新過(guò)程都將失敗,瀏覽器繼續(xù)全部使用老的緩存。
其實(shí),不必明確的列出Application Cache鏈接到的頁(yè)面,默認(rèn)情況下,任何包含html元素manifest屬性的頁(yè)面都會(huì)緩存,這些自動(dòng)緩存的頁(yè)面稱(chēng)為主條目,而清單中列出的文件稱(chēng)為詳細(xì)條目,如果某些文件需要在線訪問(wèn),可以創(chuàng)建 “ 白名單 ”。像在NETWORK下的條目,這些文件通常稱(chēng)之為網(wǎng)絡(luò)條目,每次聯(lián)網(wǎng),每次都要請(qǐng)求服務(wù)器。
第一行CACHE MANIFEST是固定的格式,且必須要寫(xiě)在第一行,也必須要有,NETWORK和FALLBACK為可選項(xiàng)。
FALLBACK中的資源必須和manifest文件同源。
引用manifest的html必須與manifest文件同源,在同一個(gè)域下。
當(dāng)manifest文件發(fā)生改變時(shí),資源請(qǐng)求本身也會(huì)觸發(fā)更新
注釋不僅僅起到不執(zhí)行的作用,上述已經(jīng)詳細(xì)解釋了,可以是版本號(hào),時(shí)間戳或者md5碼等等。
manifest文件中的cache部分不能使用通配符,必須手動(dòng)指定,沒(méi)有自動(dòng)化工具。
在開(kāi)發(fā)過(guò)程中,通過(guò)ajax與WCF進(jìn)行數(shù)據(jù)交互時(shí),常常頭一次或頭幾次數(shù)據(jù)加載成功,以后均加載失敗。
因?yàn)閱⒂玫膚eb離線緩存機(jī)制,所以每次ajax加載數(shù)據(jù)時(shí)是從本地緩存文件中讀取的,用的是ajax的get模式,因?yàn)間et模式緩存,所以不會(huì)重新向服務(wù)器請(qǐng)求數(shù)據(jù),導(dǎo)致數(shù)據(jù)加載失敗。
改成ajax post方式后,數(shù)據(jù) never cache,所以每次刷新網(wǎng)站,均會(huì)向service請(qǐng)求數(shù)據(jù)。
報(bào)錯(cuò): Application Cache Error event: Manifest fetch failed (404)
解決方法:
manifest 文件需要配置正確的 MIME-type,即 “text/cache-manifest”。
manifest 的 contentType = text/cache-manifest,擴(kuò)展名建議為 .appcache
且必須在 web 服務(wù)器上進(jìn)行配置,不同的服務(wù)器配置方法不一樣。
頁(yè)面離線,ajax更新。
首先,你可以修改下 manifest 文件來(lái)更新這個(gè)頁(yè)面,但是作為文章內(nèi)容頁(yè)面離線以后,就會(huì)存儲(chǔ)在本地了,如果你是一篇章的話(huà),那么這個(gè)文章的內(nèi)容頁(yè)就被存下來(lái)了,你如果以相同的 url 去訪問(wèn),不管你文章里面的數(shù)據(jù)更新沒(méi)有,這個(gè)離線下來(lái)的頁(yè)面都不會(huì)更新了 ( 除非你更新manifest 文件 ) 。所以,你所有的動(dòng)態(tài)數(shù)據(jù),都得用 ajax 方式去獲取,就像客戶(hù)端一樣,離線的頁(yè)面應(yīng)該是一個(gè)沒(méi)有數(shù)據(jù)的空殼,然后通過(guò) ajax 去拉去數(shù)據(jù)填補(bǔ)這個(gè)空殼。然后要注意的是,ajax 的請(qǐng)求地址,要寫(xiě)到manifest 的 network 中。
離線頁(yè)面的更新(長(zhǎng)尾問(wèn)題)
網(wǎng)站更新了,如何更新用戶(hù)本地的離線頁(yè)面呢?
與很多文章中說(shuō)的一樣,先上線你的文件,然后修改一下頁(yè)面中引入的cache.manifest文件即可,比如修改下注釋?zhuān)薷暮?,如果再訪問(wèn)頁(yè)面,就會(huì)先去校驗(yàn)manifest 時(shí)候有更新,如有更新,再次刷新頁(yè)面的時(shí)候,頁(yè)面就會(huì)更新了。
長(zhǎng)尾問(wèn)題(非常重要):
就像前面說(shuō)到的一樣,如果你的 manifest 文件更新了,你訪問(wèn)頁(yè)面,需要刷新一次,更新的頁(yè)面才能 load加載進(jìn)來(lái),那么這樣就有一個(gè)問(wèn)題,如果你的后端數(shù)據(jù),就是給 js ajax 接口的數(shù)據(jù)變化了,你對(duì)應(yīng)的 js 也修改了。那么你修改 manifest 上線的時(shí)候,第一次開(kāi)頁(yè)面,頁(yè)面就會(huì)出 bug 了。再刷一次頁(yè)面,就好了。那么,這個(gè)第一次訪問(wèn)的 bug ,是我們不想看到的。
而且你不能知道用戶(hù)什么時(shí)候第二次再來(lái)訪問(wèn)你的頁(yè)面,所以你的頁(yè)面一旦使用 manifest 離線,就像客戶(hù)端一樣,這樣就出現(xiàn)了長(zhǎng)尾問(wèn)題。還好, manifest 有一些 js 接口,可以來(lái)判斷, load 更新文件。
cache.status屬性返回當(dāng)前離線應(yīng)用狀態(tài)
- UNCACHED ( 數(shù)值 0) :未啟用離線應(yīng)用
- IDLE ( 數(shù)值 1) :已開(kāi)啟離線應(yīng)用,但本地緩存的資源是最新的,并且未標(biāo)記為廢棄資源
- CHECKING ( 數(shù)值 2) :當(dāng)前更新緩存的狀態(tài)為 “ 檢查中 ”
- DOWNLOADING ( 數(shù)值 3) :當(dāng)前更新緩存的狀態(tài)為 “ 下載資源中 ”
- UPDATEREADY ( 數(shù)值 4) :當(dāng)前更新緩存的狀態(tài)為 “ 更新完畢 ”
- OBSOLETE ( 數(shù)值 5) :已開(kāi)啟離線應(yīng)用,但緩存資源都已標(biāo)記為廢棄
如果文件超出緩存5M的大小,會(huì)造成什么。
比如我A頻道維護(hù)了自己的Application Cache,B頻道也維護(hù)了自己的,這個(gè)時(shí)候A頻道如果使用達(dá)到了一個(gè)峰值,會(huì)導(dǎo)致B頻道所有的緩存失效。
所以,建議Application Cache存儲(chǔ)公共資源,不要存儲(chǔ)業(yè)務(wù)資源!
由更新機(jī)制來(lái)說(shuō),首次更新manifest時(shí),因?yàn)轫?yè)面加載已經(jīng)開(kāi)始甚至已經(jīng)完成,緩存更新尚未完成,瀏覽器仍然會(huì)使用過(guò)期的資源;瀏覽器是當(dāng)Application Cache有更新時(shí),該次不會(huì)使用新資源,第二次才會(huì)使用。這個(gè)時(shí)候update事件中執(zhí)行window.reload事件。
window.applicationCache.addEventListener("updateready", function(){
window.location.reload()
});
由上例可以知道,緩存的不只是顯示定義的文件,比如上例中的applicationcache/時(shí)便會(huì)默認(rèn)保存index.html為映射的數(shù)據(jù),并且包含demo.appcache文件,很多時(shí)候會(huì)遇到一次文件更新線上老是不更新,這個(gè)時(shí)候隨便在manifest配置文件中做一點(diǎn)修改即可更新。
做一下代碼更改:
<html manifest="A.appcache">
=>
<html manifest="B.appcache">
這個(gè)時(shí)候如果不做A.appcache的更新的話(huà),緩存將不會(huì)更新,原因是index.html被緩存了,檢測(cè)的仍然是原manifest清單
各個(gè)頁(yè)面統(tǒng)一管理自己的manifest清單,意思是a頁(yè)面配置了common.js,b頁(yè)面也配置了common.js,意思是a頁(yè)面更新后,
b頁(yè)面的manifest不更改的話(huà),b頁(yè)面依舊讀取的是老版本的文件,這個(gè)有一定道理卻也有一定浪費(fèi),需要公共頁(yè)面做處理。
那么以上就是有關(guān)于“在HTML5實(shí)現(xiàn)應(yīng)用程序緩存(Application Cache)的方法分享!”這個(gè)方面的相關(guān)內(nèi)容分享!那么到此這篇關(guān)于這篇文章就介紹到這了,更多相關(guān)HTML5的內(nèi)容我們都可以在W3Cschool進(jìn)行搜索和了解!