localStorage的黑科技-js和css緩存機(jī)制
一、發(fā)現(xiàn)黑科技的起因
今天在微信公眾號(hào)看到一篇技術(shù)博文,想用印象筆記收藏,所以發(fā)送了文章鏈接到pc上。然后習(xí)慣性地打開控制臺(tái),看看源碼,想了解下最近微信用了什么新技術(shù)。
呵呵,以下勾起了我偵探的欲望。頁(yè)面加載后的異常點(diǎn)就是只加載了一個(gè)js,如下圖所示:
我很詫異,為什么已經(jīng)開啟了Disable cache,js只加載了一個(gè),而且體積這么小。接著,我按住Ctrl+O進(jìn)行資源文件查找,發(fā)現(xiàn)我被“忽悠”了。其實(shí)根本就不止一個(gè)js文件。
腦袋里靈光一閃,不會(huì)是用localStorage做了緩存吧?!趕緊看了下localStronge,還真是。。。。
心里一陣澎湃,這不是我之前就想實(shí)現(xiàn)的加載性能優(yōu)化的想法嗎!乖乖,我孤陋寡聞了,已經(jīng)有前端團(tuán)隊(duì)實(shí)現(xiàn)了代碼。
二、談?wù)勎募虞d方面的優(yōu)化思路
通常,前端的資源文件加載優(yōu)化,就是在文件不修改迭代的情況下,盡可能多地利用緩存,避免多次下載同樣的文件。
一般的做法就是盡量延長(zhǎng)資源的有效期,也就是設(shè)置 Cache-Control里的max-age,使頁(yè)面資源請(qǐng)求的返回碼為304,讓瀏覽器直接使用本地緩存。
雖然pc端的協(xié)商緩存(304)很快,但手機(jī)端因?yàn)榫W(wǎng)絡(luò)原因,協(xié)商緩存的效果就沒pc端那么好了。而且,手機(jī)會(huì)經(jīng)常清除本地緩存,所以文件緩存的時(shí)間也不會(huì)很長(zhǎng)。
這個(gè)時(shí)候,localStorage就派上用場(chǎng)了。
localStorage相比cookie,可以緩存大體積的數(shù)據(jù),而且是永久有效。所以,如果把js資源和css資源存儲(chǔ)在localStorage中,則可以省去發(fā)送http請(qǐng)求所消耗的時(shí)間,大大提高用戶的瀏覽體驗(yàn)。
三、用localStorage做資源緩存需要解決的問題
3.1 版本更新機(jī)制
只要一個(gè)項(xiàng)目還在迭代開發(fā),就難以避免需要更新資源文件。
普通的資源請(qǐng)求,可以根據(jù)
文件名+md5 http://res.wx.qq.com/mmbizwap/zh_CN/htmledition/js/biz_wap/moon32ebc4.js
或者
在資源鏈接后面加上特定的后綴http://1.ss.faisys.com/js/comm/fai.min.js?v=201612051739
做標(biāo)識(shí)來判斷是否需要更新資源。
如果用localStorage做,則需要一套新的緩存更新機(jī)制。
3.2 搭建更新代碼的腳手架
使用localStorage緩存,則需要一個(gè)新的腳手架來管理資源文件的讀取和寫入。
3.3 后臺(tái)輸出一份資源配置信息
因?yàn)樾枰岸俗鲑Y源更新,所以后臺(tái)要輸出一份依據(jù)給前端做判斷用,也就是需要一份資源配置信息。前端根據(jù)配置信息,進(jìn)行匹配和比較,最終決定 使用localStorage緩存,還是重新發(fā)起請(qǐng)求,下載最新的資源文件。
3.4 存在XSS安全隱患
localStorage中的信息,客戶端是可以任意修改的。如果哪個(gè)黑客想練手一下,可以任意注入js代碼。那么,在頁(yè)面刷新的時(shí)候,注入的代碼也將會(huì)被執(zhí)行。
四、微信的做法解析
4.1 版本標(biāo)識(shí)
以__MOON__a/a_report.js為例,版本信息用key __MOON__a/a_report.js_ver存儲(chǔ),存儲(chǔ)的value為//res.wx.qq.com/mmbizwap/zh_CN/htmledition/js/a/a_report32e586.js。
如果按普通加載方式,直接將該value取出來,設(shè)置到script節(jié)點(diǎn)的src屬性,即可完成加載。
微信判斷該版本是否最新,就是用該value值與后臺(tái)輸出的配置信息進(jìn)行比較,最后得出是否更新的結(jié)果。
如果value值與配置信息一致,則使用緩存。否則,重新發(fā)起請(qǐng)求加載。
4.2 腳手架
可以看出,微信使用的是自己開發(fā)的腳手架moon.js,在這個(gè)網(wǎng)頁(yè)中的實(shí)際文件名是moon32ebc4.js。
因?yàn)槭腔煜^變量名的文件,所以要看出具體代碼的走向,有點(diǎn)費(fèi)勁,這里就不做分析了。
4.3 資源配置信息
因?yàn)槟_手架moon.js需要資源配置信息才能正常工作,所以配置信息一定會(huì)在moon.js之前輸出。
依次查看moon.js之前的script標(biāo)簽,發(fā)現(xiàn)了window.moon_map這個(gè)json對(duì)象。
利用控制臺(tái)輸出該變量查看信息如下:
看到這里,可以明確一個(gè)點(diǎn):這就是更新機(jī)制所必備的資源配置信息表了。
而且,可以看出,該配置信息json對(duì)象的key,就對(duì)應(yīng)localStorage中的key。同理,value值也是一一對(duì)應(yīng)。
4.4 XSS攻擊
此處是為了驗(yàn)證微信的緩存機(jī)制是否存在XSS攻擊,看到這里的童鞋可千萬不要去做壞事。
我在一個(gè)js緩存代碼中,插入alert("hehe");,看頁(yè)面刷新的時(shí)候,是否會(huì)出現(xiàn)該彈窗,來驗(yàn)證是否存在攻擊漏洞。
刷新頁(yè)面后,結(jié)果如下圖:
可以看出,微信也沒有解決這類問題。所以,這種緩存機(jī)制,還是有先天不足的。
4.5 測(cè)試微信的更新機(jī)制
修改localStorage中 key __MOON__a/a_report.js_ver對(duì)應(yīng)的value值,讓微信的腳手架moon.js更新__MOON__a/a_report.js,刷掉我剛才主動(dòng)插入的代碼。
這里,我修改文件名為***587.js(原來的文件名為***586.js)。接著F5刷新頁(yè)面。
結(jié)果為:report.js代碼更新了,版本號(hào)也恢復(fù)回 ***586.js。
五、結(jié)論
localStorage緩存有其用武之地,但不是萬能的。需要注意以上提及的坑。
可以應(yīng)用的場(chǎng)景我歸納為以下幾點(diǎn):
1. 非首屏渲染需要的css文件,可以做LS緩存。
首屏渲染需要的css,需要按常規(guī)方式輸出,因?yàn)镾EO需要,不然爬蟲爬取頁(yè)面的時(shí)候,頁(yè)面效果會(huì)很不好。而非首屏的css,則可以用LS緩存,減少資源下載時(shí)間。
2. 展示類、動(dòng)畫類等非業(yè)務(wù)主要邏輯的代碼,可以做LS緩存。
這樣,可以一定程度上避免業(yè)務(wù)層的安全漏洞。當(dāng)然,前端再怎么做防護(hù)都是一層薄紙。重要的,還是后臺(tái)接口要做好安全保護(hù)。
3. 移動(dòng)端可以做LS緩存。PC端做LS緩存,起到的優(yōu)化作用不大。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- 使用jquery讀取html5 localstorage的值的方法
- JavaScript使用localStorage存儲(chǔ)數(shù)據(jù)
- JS 中LocalStorage和SessionStorage的使用
- JS中LocalStorage與SessionStorage五種循序漸進(jìn)的使用方法
- JS中利用localStorage防止頁(yè)面動(dòng)態(tài)添加數(shù)據(jù)刷新后數(shù)據(jù)丟失
- JS實(shí)現(xiàn)本地存儲(chǔ)信息的方法(基于localStorage與userData)
- JavaScript中l(wèi)ocalStorage對(duì)象存儲(chǔ)方式實(shí)例分析
- 移動(dòng)端使用localStorage緩存Js和css文的方法(web開發(fā))
- 詳解JavaScript中l(wèi)ocalStorage使用要點(diǎn)
- Javascript 計(jì)算字符串在localStorage中所占字節(jié)數(shù)
- JS localStorage實(shí)現(xiàn)本地緩存的方法
- JS+HTML5本地存儲(chǔ)Localstorage實(shí)現(xiàn)注冊(cè)登錄及驗(yàn)證功能示例
相關(guān)文章
JavaScript計(jì)算器網(wǎng)頁(yè)版實(shí)現(xiàn)代碼分享
這篇文章主要為大家詳細(xì)介紹了JavaScript計(jì)算器網(wǎng)頁(yè)版實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07uniapp中canvas繪制圖片內(nèi)容空白報(bào)錯(cuò)的原因及解決
最近有個(gè)需求就是要用canvas畫個(gè)分享的海報(bào),所以這里總結(jié)下,這篇文章主要給大家介紹了關(guān)于uniapp中canvas繪制圖片內(nèi)容空白報(bào)錯(cuò)的原因及解決方法,需要的朋友可以參考下2023-09-09JS網(wǎng)頁(yè)播放聲音實(shí)現(xiàn)代碼兼容各種瀏覽器
JS網(wǎng)頁(yè)播放聲音有多種方法可以實(shí)現(xiàn),不過兼容各種瀏覽器的就沒有幾個(gè)了,不過本文的這個(gè)示例或許對(duì)大家有所幫助2013-09-09javascript函數(shù)中參數(shù)傳遞問題示例探討
本節(jié)主要與大家探討下javascript函數(shù)中參數(shù)傳遞問題,有不明白的朋友可以參考下2014-07-07JQuery 表格操作(交替顯示、拖動(dòng)表格行、選擇行等)
JQuery 表格操作包括交替顯示、拖動(dòng)表格行、選擇行等功能,大家可以參考下。2009-07-07JSON.stringify(遞歸)與?JSON.parse(有限狀態(tài)自動(dòng)機(jī))的實(shí)現(xiàn)代碼
這篇文章主要介紹了JSON.stringify(遞歸)與?JSON.parse(有限狀態(tài)自動(dòng)機(jī))的實(shí)現(xiàn),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08