四種有能力取代Cookies的客戶端Web存儲方案
譯文目前在用戶的網絡瀏覽器中保存大量數據需要遵循幾大現有標準,每一種標準都擁有自己的優勢、短板、獨特的W3C標準化狀態以及瀏覽器支持級別。但無論如何,這些標準的實際表現都優于廣泛存在的cookies機制。
今天的Web應用程序開始在客戶端中執行大量數據處理工作,甚至可能需要以脫機方式完成任務。可以說,客戶端數據存儲對于下一代Web應用程序的發展起到了至關重要的作用。
然而直到現在,cookies仍然是用戶瀏覽器中最常見的數據存儲機制。如果一款Web應用需要重復訪問某些數據,則只有兩種方式可供選擇:要么再次向服務器發送請求以獲取數據,要么讀取保存在cookies中的內容。
cookies機制只能提供有限的存儲空間——最多4K或者4096字節——因此總量較大的數據會被拆分成4K大小的塊從而加以明確而直接地管理。
但這種方式對于存儲的協作及管理而言顯然并不可行,因此我們需要拿出一套新的替代性方案。
cookies的承受能力太過孱弱
網絡瀏覽器最初只是通過HTTP并解析HTML實現應用程序對文檔內容的加載。但在此后不久,第一款網景瀏覽器出現了,它滿足了用戶的一系列實際需求,但卻需要利用本質上無狀態的HTTP協議來通過某些機制實現狀態追蹤。面對這一問題,Lou Montulli于1994年創造了瀏覽器cookie(當初被稱為‘magic cookie’),并首次亮相于Mosiac網景瀏覽器0.9b版本之上。
在通用網關接口(簡稱CGI)提供的服務器端腳本訪問功能與cookies的共同輔助下,最早的Web應用程序終于變成現實。最終,我們開始沿著這條小路將瀏覽器轉化成為一種通用的應用程序平臺。
然而cookies機制存在著嚴重缺陷。正如前面所提到,它只能存儲極少量數據,而且很容易受到各類攻擊活動的影響,這樣的狀況讓我們很難利用其存儲個人信息及敏感數據、從而極大限制了它的使用范圍。
cookies會介入到從瀏覽器發向服務器端的每一條HTTP請求當中。假設一個網頁中包含的四張圖片、一個外部CSS文檔外加JavaScript文檔。系統會為該域設置一個4K的cookie,瀏覽器則分四次將該cookie轉發至服務器端——一次針對HTML頁面、一次針對每張圖片、一次針對CSS文檔再加上一次針對JavaScript文檔。
令問題進一步復雜化的原因在于,這個理論上為4K大小的cookie需要從瀏覽器端傳輸至服務器端;由于大部分用戶使用的是異步互聯網連接,即上傳速度低于下載速度,因此在HTTP響應頭中傳輸cookie數據一定會造成不必要的帶寬占用。
由于上述限制因素的存在,大部分cookies的體積都要遠小于4K。谷歌建議每個cookie的實際大小不要超過400字節(或者200個字符),從而實現最佳性能表現。他們還建議稱,在圖片、CSS以及JavaScript等來自獨特域的靜態文件應該禁用cookies機制。
由于cookies機制在本地存儲領域存在諸多問題,目前已經出現一系列新興方案,旨在撥亂反正、保質保量完成任務。近幾個月以來,已經有兩款方案走上正軌、得到W3C的強烈推薦——它們能夠很好、甚至比我們預想中更好地幫助瀏覽器支持本地存儲功能。
目前我們可以從四種主流客戶端數據存儲機制中做出選擇,它們分別是:Web SQL、IndexedDB、Web Storage以及Application Cache。下面我們就逐一對每套方案加以評述,并探討它們在運作及效果方面的各自特性。
Web SQL: 擅長(但是否有些過時?)數據庫創建與執行
Web SQL是一種利用數據庫進行數據存儲并利用SQL處理檢索任務的API。最近,Safari、Chrome以及Opera等知名瀏覽器紛紛在Web SQL與IndexedDB的競爭之中選擇了前者。不過2010年時,SQLite還是惟一一款能夠與Web SQL協作的數據庫,而W3C出于安裝基礎較小的理由而停止對這套方案進行支持。
Web SQL的工作機制相當新奇,下面我們就一起來看示例代碼。
Web SQL數據庫的使用感受與關系類數據庫及SQL非常相似。使用這款數據庫的第一步在于創建并打開。如果大家不希望額外創建一套數據庫,那么完全可以直接開始使用,API本身會自動完成創建工作。
下面我們來看一部分用于數據庫創建的代碼:
- var db = openDatabase('cats', '1.0',
- 'a catalog of my cats', 2 *1024 * 1024);
按照從左到右的順序,openDatabase后面的參數依次代表著數據庫名稱、版本號、文字說明以及預計數據庫大小。
數據庫創建完成之后,大家就可以著手使用了。在WebSQL數據庫上執行SQL與創建事務對象并加以執行一樣簡單:
- db.transaction(function (tx) {
- tx.executeSql('CREATE TABLE cats (id unique, name)');
- tx.executeSql('INSERT INTO cats (id,name) VALUES (1,"Mr. Jones")');
- });
盡管Safari、Chrome、Opera以及Mobile Safari都支持這款API,但自2010年以來Web SQL就沒有發生過任何變化,因此它不太可能成為本地存儲的新型標準。
Web Storage: 取cookies所長、去cookies所短
Web Storage利用一種簡單的方法在用戶的瀏覽器中存儲鍵/值對。但它與cookies之間的相似之處也就僅此而已了。
• Web Storage是一套持久性方案。一旦某個值被存儲之后就不會再消失或者終止,除非被應用程序或用戶明確刪除。
• Web Storage能夠處理大量數據。目前瀏覽器的總體存儲區域大小最高為5MB。
• Web Storage無需依賴于服務器,而且不必向服務器端發送數據。當然,大家可以隨意實現本地化數據存儲并將其與服務器進行異步式同步,但Web Storage的表現始終出色而且在離線與在線狀況下都能正常生效。
• Web Storage提供四種主要方法——getItem(鍵);setItem(鍵、值);removeItem(鍵)以及clear()。
最后,Web Storage包含兩種完全不同的存儲類型:SessionStorage以及LocalStorage。
SessionStorage的作用在于保證被保存在當前瀏覽器窗口當中的數據僅作用于該窗口。舉例來說,當大家使用電子商務類應用程序時,利用SessionStorage來記錄用戶的購物車信息能夠避免誤操作所帶來的二次購買狀況。
下面再來看LocalStorage,它專門負責保存可同時作用于同一瀏覽器之下各窗口及標簽之間的數據。因此,如果大家在Chrome當中打開了三個關于同一網站的窗口,那么三者能夠共同使用同一套LocalStorage容器。相比之下,如果我們打開三個內容彼此獨立的網站窗口,那么每一個都將使用彼此獨立的容器。同樣,如果大家在不同的瀏覽器當中打開同一個網站,那么每種瀏覽器都需要使用屬于自己的容器,因此無法共享同一套通用的運行環境。
要設置一套新的鍵-值對并進行檢索,大家可以使用下列JavaScript命令:
- //first set firstname equal to Sparky.
- localStorage.setItem( "firstname", "Sparky" );
- //next, get the value of firstname (hint, it will be Sparky).
- localStorage.getItem( "firstname" );
今年夏天,Web Storage API正式獲得W3C推薦標準這一殊榮。展望未來,Web Storage完全有可能在一切原本cookies發揮作用的舞臺上成為新的處理方案。
但Web Storage能做的還很多。如果大家的數據集并不太大,Web Storage還提供另一種可能是最為簡便的處理辦法——甚至比cookies更簡便——從而順利搞定瀏覽器中鍵-值對的設置與檢索工作。
#p#
IndexedDB:可搜索且不存在文件大小限制
Indexed Database是一款利用索引化事務性數據庫對用戶計算機上的數據進行保存與索引的API。IndexedDB帶來更快速、更精妙的數據存儲與檢索效果,在這方面采用簡單鍵-值對存儲機制的cookies以及Web Storage都只能甘拜下風。
與Web Storage一樣,IndexedDB API在今年夏天(也就是2013年7月)向Web標準邁進了一大步,成為W3C候選推薦名單中的一員。
與Web Storage相比,IndexedDB帶來四項具體提升:
- 能夠對索引數據進行高效搜索。
- 數據庫能夠將多個值保存為一個鍵,而鍵-值機制則要求每個鍵都必須惟一。
- 事務型數據庫提供多項針對系統及應用程序故障的保護措施。如果事務流程未能正常完成,則將通過回滾方式進行恢復。
- IndexedDB數據庫對數據內容的大小不加限制。在火狐當中,瀏覽器會要求利用權限將數據庫的容量提升到超過50MB,而IndexedDB的實際數據存儲量限制直接取決于分卷或者磁盤驅動器本身的容量極限。
除了Safari之外的所有主流瀏覽器都已經支持IndexedDB。不過由于Safari支持Web SQL,因此我們完全可以利用IndexedDB夾層(或者被稱為shim)通過Web SQL實現IndexedDB的功能與語法。
要使用IndexedDB,第一步需要打開一套數據庫。
- var request = indexedDB.open("myDatabase");
在數據庫創建完成之后,大家可以創建一個存儲對象(與表格非常類似)并向其中添加數據。假設我們需要向其中添加如下數據:
- const petData = [
- { id: "00-01", firstname: "Butters", age: 2, type: "dog" },
- { id: "00-02", firstname: "Sammy", age: 2, type: "dog" }
- ];
接下來,我們可以創建數據存儲機制并通過下列代碼加以使用。請注意onupgradeneeded的處理方式:我們在改變數據庫結構時需要用到這一方法。
- request.onupgradeneeded = function(event) {
- var db = event.target.result;
- var objectStore = db.createObjectStore("customers", {keyPath: "id"});
- for (var i in customerData) {
- objectStore.add(customerData[i]);
- }
- }
IndexedDB擅長于搜索大型數據庫集,并能夠通過將結構化數據移動至客戶端來提高Web應用程序的性能表現。目前它已經非常接近W3C的推薦級別,而且能夠被用于全部瀏覽器平臺——盡管具體實施方式有所區別,如前文所述,在Safari中需要借用夾層機制。
Application Cache: 讓離線客戶端存儲成為現實
Application Cache與前面提到的其它客戶端數據存儲APi都不一樣,但它同樣值得關注,因為它已經成為離線客戶端Web應用程序的重要組成部分。
Application Cache使用的是一套緩存列表。所謂列表,只是一個非常簡單的文本文檔,其中列舉了所有應該或不應該通過緩存機制處理的資源條目,從而指導瀏覽器下載特定文件、加以保存并在必要時予以使用——而不必再向服務器發出重復請求。目前所有主流網絡瀏覽器都支持Application Cache機制。
要使用Application Cache,我們需要首先在包含有緩存對象文件的網站中保存一個擴展名為為.appcache的文本文件。根據所使用Web服務器的具體類型,我們可能需要為.appcache文件創建一個自定義MIME類型以確保它們能夠正確作用于瀏覽器并可被作為應用程序緩存文件讀取。
下面我們列舉一個緩存列表文件作為范例:
- CACHE MANIFEST
- CACHE:
- /css/styles.css
- /js/javascript.css
- /img/logo.gif
- FALLBACK:
- /img/weathertoday.png /img/weathernotavailable.png
- NETWORK:
現在我們來詳細解讀其中的內容:
- CACHE部分用于告知瀏覽器哪些資源需要進入緩存以實現離線查看。這些文件會一直保留于緩存當中中,直到緩存列表發生變化。請記住這項要求,非常重要。
- FALLBACK部分則用于告知瀏覽器哪些要顯示的文件會取代非緩存資源。舉例來說,在上面的FALLBACK部分中,我們可以推測如果latestweather.png圖片無法被正確下載,那么當前天氣狀況無法在離線狀態下實現圖片顯示。
- NETWORK部分用于告知瀏覽器哪些資源只能通過在線模式進行獲取。結尾部分的星號表示目前緩存中不存在任何一種網絡資源。
Application Cache是一款出色的工具,只要使用得當、它幾乎沒有什么缺點。其實正確使用是一門學問:如果大家單純把網站上的所有內容都添加到緩存當中,那么訪問者們會很快發現網站內容永遠不會發生變化。如果大家只把變化頻率不高的內容保存在緩存當中,或者努力保證緩存列表始終處于最新并在上傳文件后及時發布新的列表版本,那么Application Cache將帶來幾乎與在線模式無異的出色離線應用程序運行效果。
本地瀏覽器存儲在過去幾年中迎來了一輪重大變革。不同API及推薦項目所使用的多種多樣而且彼此相近的名稱讓我們很難弄清哪些可以繼續使用、而哪些應該及時淘汰。總而言之,瀏覽器數據存儲領域擁有多種不同方式可供選擇,而且每一種都有非常充分的存在價值。
無論如何,開發人員們努力通過cookies向服務器發送簡單的小型名-值對的時代已經結束。今天,我們擁有更多優秀的方案可供使用。
原文鏈接:http://www.cio.com/article/739064/4_Client_Side_Web_Storage_Options_That_Replace_Cookies