今天在項目中遇到了一個問題,localStorage存儲超出限制。報錯信息如標題。這個是因為最近做了一波優化,把導航欄和一些用戶信息本地化存儲,都放在localStorage里,也不是每個用戶會出現這種問題。
其實同一個域名下可能存在幾十上百條業務線,每條業務線都可能因為各種理由往 localStorage 里塞東西,跨頁面傳數據啦、緩存啦、離線化啦、性能優化啦...,5M 看起來很多,其實很快就用完了。而開發時基本無感知,是因為大家都只訪問自己的業務,但用戶會訪問各種業務,時間一久,很容易就存滿了,凡是嚴重依賴 localStorage 的業務流程都存在風險。
Hybrid APP:一種容易想到的方案是,當 localStorage 存滿后降級到 sessionStorage 里。看上去沒啥問題,但實際業務中 app 內 h5 頁面跳轉常常采用新打開 webview 的方式,這么做的好處是關閉一個 webview 可以直接回到上一個頁面,而不用重新加載頁面,對於訂單填寫這類帶有狀態的頁面就很需要這么做。新打開 webview 等於新打開一個會話,而 sessionStorage 只能存在於同一個會話中,因此 sessionStorage 無法跨頁面共享。
那降級到 cookie 里呢?cookie 一共才 50 個,總大小不超過 4k,作為 backup 過於脆弱,而且還會影響請求的效率。如果后端對請求頭大小做了限制,還可能產生 413 錯誤,導致請求被攔截。
那降級到 url 上呢?很麻煩。比如有一個交互流程是這樣的:頁面 A => 頁面 B => 頁面 C,如果頁面 A 的數據要傳到頁面 C,就得通過頁面 B 做一層中轉。而且 url 長度也是有限制的。
單頁面應用在不影響業務的情況下,可以直接從localStorage里降到sessionStorage。
我們還可以求助客戶端同學,通過 js bridge 提供一個仿 localStorage 的東西,不過要考慮版本的問題,新版 app 里使用了客戶端提供的 store,怎么兼顧老版 app,而且還要考慮兼容瀏覽器、微信。所以這種方案也只能解決一部分問題,當然,如果 h5 的流量絕大多數都在 app 里,那么這種方案是可以解決一大部分問題的,不過客戶端提供的存儲可不見得比原生的存儲可靠,還是得加 backup。
我們還可以求助后端同學,多加幾個字段甚至多加幾個接口,不過這涉及到核心業務流程的改造,風險不小,而且不見得能完全解決問題,也無法永久的解決問題。
我們還可以來一招互相傷害大法,那就是把別人存的東西都刪掉。。。
還有一個很討厭的事情:safari 在隱私模式下不支持 localStorage 的存取(ios11 以下),這種情況比較罕見,但如果出了客訴,也是個大坑。
localStorage 歸根結底就兩個作用:持久化存儲與跨頁面傳數據。持久化存儲不會出問題,存不進去就存不進去唄,取不出來就去其它地方取,或者不取。問題就出在跨頁面傳數據上,上一個頁面因為 localStorage 存滿導致數據沒有寫入,下一個頁面讀取數據為空,從而導致錯誤。
理想的方案
假設我們回到起點,從零建設前端工程,我們怎么避免 localStorage 存滿的問題?
1、划分域名。各域名下的存儲空間由各業務組統一規划使用
2、跨頁面傳數據:考慮單頁應用、優先采用 url 傳數據
3、最后的兜底方案:清掉別人的存儲
目前的問題是它既不存,也不跳轉,稍改動一下,如下:
try { localStorage.setItem("nearbycorp",JSON.stringify(this.state)); localStorage.setItem('nearbycorp_scrolltop', $('.list .am-list-view-scrollview')[0].scrollTop); }catch (err){ console.log(err) }finally { location.hash = "/customer/detail/" + corp.id; }
因為該頁面存的是跳轉到另外一個hash時存儲了當前頁面的篩選條件和滾動高度,結果就是不會滾動到剛剛的瀏覽區域。對用戶造成一定的影響。所以還是直接存儲到sessionStorage里比較好,不會影響用戶。
查詢localStorage限制的網址: http://dev-test.nemikor.com/web-storage/support-test/
try { sessionStorage.setItem("nearbycorp",JSON.stringify(this.state)); sessionStorage.setItem('nearbycorp_scrolltop', $('.list .am-list-view-scrollview')[0].scrollTop); }catch (err){ console.log(err) }finally { location.hash = "/customer/detail/" + corp.id; }
當然,這個問題應該從項目創建就考慮到,不必要存到localStorage的數據盡量不要存,避免后面出現這種問題。
