shtml頁面局部緩存的實現(xiàn)
平時在web開發(fā)中,對于shtml頁面,用得最多的SSI指令是include。語法規(guī)則如下:
<!–#include virtual=”shtmlCache/header.shtml” –>
這樣可提高代碼重用性以及可維護(hù)性,因此,一般都把公共文件,如頭部、尾部、側(cè)邊欄、公共的JS等做成一個單獨的文件,然后通過include指令包含進(jìn)來,這樣整個站點的頭部、尾部、側(cè)邊欄、公共JS等,都可以被引入到shtml頁面中。后面需求更改,比如產(chǎn)品需要更改站點頭部,也只需要更改頭部文件,就可以實現(xiàn)全站頭部更新??梢娡ㄟ^include指令包含公共文件,可以使shtml頁面的維護(hù)性和重用性大大增強。
一般來說,對于shtml頁面,一個站點,每個頁面都會有相同的公共文件,比如頁面的頭部、尾部、側(cè)邊欄目、公共JS等。訪問站點下的每一個頁面,相同的公共文件,都需要重復(fù)從服務(wù)器下載。從性能和帶寬角度看,重復(fù)下載相同內(nèi)容對性能不利,同時也會占用帶寬。因此include進(jìn)來的公共文件,是否有辦法緩存這些文件呢?這就是這里需要重點討論的內(nèi)容。 假設(shè)有這樣一個站點,包含有頁面頭部、側(cè)邊欄、頁面尾部、公共JS。布局如下圖:
從上面的網(wǎng)頁布局結(jié)構(gòu)可看出,頁頭、側(cè)邊欄、頁尾都是屬于公共的內(nèi)容,HTML 代碼樁如下:
實現(xiàn)原理:
需要判斷include的文件是否緩存過,如果緩存過,則不會通過include來包含對應(yīng)的內(nèi)容。ssi有判斷的指令,語法如下:
<!–#if expr=”test_condition” –>
< !–#elif expr=”test_condition” –>
< !–#else –>
< !–#endif –>
我們可通過SSI指令來判斷是否緩存過。同時可利用html5的localStorage來對代碼進(jìn)行保存。
可localStorage只能夠通過JS訪問,那如何實現(xiàn)localStorage和服務(wù)器的ssi指令通信呢?這里利用到一個小技巧,借助cookie作為橋梁,不管是JS還是SSI都是可以訪問,因此可利用它來實現(xiàn)SSI和JS之間的通信。換言之,用JS寫一個cookie來標(biāo)識是否已經(jīng)緩存過相應(yīng)的內(nèi)容,然后利用SSI的if語句結(jié)合cookie來判斷是否需要include對應(yīng)的內(nèi)容。
主要流程圖如下:
示例分析:
來看一個簡單的demo。以前面頁面框架為例,假設(shè)header里面有內(nèi)容是通過JS來輸出,側(cè)邊欄是全部的HTML,現(xiàn)在要緩存header中的JS和側(cè)邊欄的HTML。先來看核心的HTML代碼(SSI部分):
再看JS寫入緩存核心代碼:
localData.loadfromCache是實現(xiàn)從localStorage讀取緩存并渲染出來,這個比較簡單,這里就不再單獨介紹,大家可以下載示例代碼來查看,或者放在支持ssi的服務(wù)器下運行。第一次訪問后,將會把對應(yīng)的公共文件進(jìn)行緩存,先查看解析后的HTML源代碼:
從上圖可以看出,第一次訪問時,因沒有緩存過,都是通過include進(jìn)行直接解析。同時通過cookie和localStorage可查看到相應(yīng)的值。
cookie信息:
第二次訪問時,再查看解析后的HTML源代碼
從上面的2個圖對比可以看出,當(dāng)公共文件沒有被緩存時,是通過解析include指令得到相應(yīng)的代碼;當(dāng)有緩存時,直接通過JS代碼從緩存中讀取;從而實現(xiàn)shtml文件局部緩存;
版本控制:
上述示例演示了shtml的局部緩存,那么緩存的版本如何控制呢?可通過cookie來保存版本號,當(dāng)有緩存的公共文件需要更新時,需要更新ssi if語句中的的版本號,也就是更新下面這行代碼中的版本號:
<!–#if expr=”${HTTP_COOKIE} = /(;)?html_aside=01(;)?/”–>
假設(shè)上一個版本號是01,現(xiàn)在版本號是02,此時需要把上述代碼更改為:
<!–#if expr=”${HTTP_COOKIE} = /(;)?html_aside=02(;)?/”–>
當(dāng)從SSI中讀取到的cookie值和新的版本號不一致時,就不會從緩存中讀取了。同理在檢測寫入緩存時,也需要檢測當(dāng)前cookie的值和當(dāng)前的版本號是否一致即可,如果不一致,則需要重新寫入緩存。
安全控制
這里把JS和HTML等代碼都緩存到localStorage中去,如果網(wǎng)站中存在XSS漏洞,則攻擊者可利用XSS漏洞篡改localStorage保存的數(shù)據(jù),這樣會擴(kuò)大網(wǎng)站的危害性,因此首先要從源頭上控制好XSS漏洞,同時也需要對從localStorage中讀取出來的數(shù)據(jù)進(jìn)行合法性校驗,以便降低安全風(fēng)險。大家可以自行設(shè)計一個算法來檢測數(shù)據(jù)的合法性。
上面的示例中只是對簡單的header中的JS和側(cè)邊欄的HTML進(jìn)行緩存,在實際項目中,需要緩存的JS和HTML代碼量要比示例中大得多,因此性能優(yōu)化的實際效果也會更加明顯。因此在實際項目中,可根據(jù)公共文件的大小來決定是否需要使用shtml緩存。另外,關(guān)于緩存時間,只需要把cookie的有效期設(shè)置為N天,則緩存的周期就變成N天了,非常靈活!
本文地址:http://m.likemindfilms.com/tutorial/wd1915.html