整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          .NET Core 的緩存篇之MemoryCache

          .NET Core 的緩存篇之MemoryCache

          對(duì)于緩存我們都已經(jīng)很熟悉了,緩存分為很多種,瀏覽器緩存、試圖緩存、服務(wù)器緩存、數(shù)據(jù)庫緩存等等一些,那今天我們先介紹一下視圖緩存和MemoryCache內(nèi)存緩存的概念和用法:

          視圖緩存

          在老的版本的MVC里面,有一種可以緩存視圖的特性(OutputCache),可以保持同一個(gè)參數(shù)的請(qǐng)求,在N段時(shí)間內(nèi),直接從mvc的緩存中讀取,不去走視圖的邏輯。

          在Asp.Net core 2.1中,官方文檔上稱:響應(yīng)緩存可減少客戶端或代理對(duì) web 服務(wù)器的請(qǐng)求數(shù)。 響應(yīng)緩存還可減少量工作的 web 服務(wù)器執(zhí)行程序生成響應(yīng)。 響應(yīng)緩存由標(biāo)頭,指定你希望客戶端、 代理和緩存響應(yīng)的中間件如何控制。

          在Asp.Net Core 2.1 中,沒有了OutputCache,換成了ResponseCache,ResponseCache必須帶一個(gè)參數(shù):Duration 單位為秒,最少設(shè)置一秒鐘

          然后再瀏覽器請(qǐng)求這個(gè)視圖

          在瀏覽器的響應(yīng)頭的Cache-Control 中出現(xiàn)max-age=5, Http協(xié)議對(duì)此的解釋是

          客戶端將不會(huì)接受其保留時(shí)間大于指定的秒數(shù)的響應(yīng)。 示例: max-age=60 (60 秒), max-age=2592000 (1 個(gè)月)

          如果在瀏覽器中禁用緩存,那么ResponseCache不會(huì)有任何效果

          Vary過濾

          關(guān)于vary在Http響應(yīng)頭的作用就是:告訴緩存服務(wù)器或者CDN,我還是同一個(gè)瀏覽器的請(qǐng)求,你給我緩存就行了,如果你換個(gè)瀏覽器去請(qǐng)求,那么vary的值肯定為空,那么緩存服務(wù)器就會(huì)認(rèn)為你是一個(gè)新的請(qǐng)求,就會(huì)去讀取最新的數(shù)據(jù)給瀏覽器

          參考資料:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

          禁用緩存(NoStore 和 Location.None)

          在Http中 :no-store,請(qǐng)求和響應(yīng)的信息都不應(yīng)該被存儲(chǔ)在對(duì)方的磁盤系統(tǒng)中

          ResponseCacheLocation.None是在Cache-Control設(shè)置一個(gè)no-cache屬性,讓瀏覽器不緩存當(dāng)前這個(gè)URL

          緩存配置(CacheProfiles)

          在一個(gè)正常的項(xiàng)目中,肯定有很多個(gè)控制器,但是不可能每個(gè)控制器的緩存策略都一樣,這時(shí)候,我們就需要一個(gè)緩存的配置來靈活應(yīng)對(duì)這個(gè)問題

          在mvc的服務(wù)注入的時(shí)候,我們可以在option里面注入進(jìn)我們的緩存策略

          然后我們?cè)谑褂玫臅r(shí)候,直接使用配置策略的名稱就好了

          這樣我們就能和之前在特性后邊配置一樣了,這是視圖緩存,下面我們就來看看MemoryCache 是個(gè)什么東東

          MemoryCache

          如果回到老版本的.NET,說到內(nèi)存緩存大家可能立馬想到了HttpRuntime.Cache,它位于System.Web命名空間下,但是在ASP.NET Core中System.Web已經(jīng)不復(fù)存在。今兒個(gè)就簡(jiǎn)單的聊聊如何在ASP.NET Core中使用內(nèi)存緩存

          有幾個(gè)問題我們需要先進(jìn)行了解:

          1.什么時(shí)候需要用到緩存?

          一般將經(jīng)常訪問但是又不是經(jīng)常改變的數(shù)據(jù)放進(jìn)緩存是再好不過了,這樣可以明顯提高應(yīng)用程序的性能。

          2.緩存的好處?

          建議百度

          使用

          不同于 ASP.NET Web 窗體和 ASP.NET MVC,ASP.NET Core 沒有內(nèi)置的 Cache 對(duì)象,可以拿來在控制器里面直接使用。 這里,內(nèi)存緩存時(shí)通過依賴注入來啟用的,因此第一步就是在 Startup 類中注冊(cè)內(nèi)存緩存的服務(wù)。如此,就得打開 Startup 類然后定位到 ConfigureServices() 方法,像下面這樣修改 ConfigureServices() 方法:

          ①首先需要在ConfigureServices中注冊(cè)緩存服務(wù)

          services.AddMemoryCache()

          為了向你的應(yīng)用程序加入內(nèi)存緩存能力,你需要在服務(wù)集合上調(diào)用 AddMemoryCache() 方法。采用這種辦法就可以讓一個(gè)內(nèi)存緩存(它是一個(gè) IMemoryCache 對(duì)象)的默認(rèn)實(shí)現(xiàn)可以被注入到控制器中去。

          ②在下面的代碼中從Home控制器的構(gòu)造函中獲取IMemoryCache實(shí)例(內(nèi)存緩存使用依賴注入來注入緩存對(duì)象)

          如你所見,上述代碼聲明了一個(gè) ImemoryCache 的私有變量。該變量會(huì)被構(gòu)造器中被賦值。構(gòu)造器會(huì)通過 DI(依賴注入)接收到緩存參數(shù),然后被存儲(chǔ)在本地變量總,提供后續(xù)使用。

          ③關(guān)于緩存的使用常用的就是Set Get Remove,一般有以下幾種做法可以參考:

          ⑴可以使用 Set() 方法來在緩存中存東西

          等你有了這個(gè) IMemoryCache 對(duì)象,就可以讀取或者向它寫入數(shù)據(jù)了。向緩存寫入數(shù)據(jù)項(xiàng)是相當(dāng)直接的

          上述代碼在 Index() 這個(gè) action 中設(shè)置了一個(gè)緩存項(xiàng)。這是通過使用 IMemoryCache 的 Set<T>() 來完成的。Set() 方法的第一個(gè)參數(shù)是鍵名,用來標(biāo)識(shí)該數(shù)據(jù)項(xiàng)。第二個(gè)參數(shù)是鍵的取值。在此例中,我們存儲(chǔ)一個(gè)字符串的鍵和一個(gè)字符串的值,而你也可以存儲(chǔ)其它類型 (原生以及自定義的類型) 的鍵值對(duì)。

          ⑵可以使用 Get 方法來從緩存中獲取到一個(gè)數(shù)據(jù)項(xiàng)

          等你向緩存中添加好了數(shù)據(jù),也許會(huì)想要在應(yīng)用程序的其它地方去獲取到該數(shù)據(jù),可以用 Get() 來做到。如下代碼會(huì)告訴你如何來做這件事情。

          上述代碼從 HomeController 的另外一個(gè)action(Show)那里獲取到了一個(gè)緩存的數(shù)據(jù)項(xiàng)。Get() 方法會(huì)指定數(shù)據(jù)項(xiàng)的類型以及它的鍵名。如果該數(shù)據(jù)項(xiàng)存在的話,就會(huì)被返回并且被賦值給 timestamp 這個(gè)字符串變量。然后這個(gè) timestamp 的值就會(huì)被傳遞給 Show 視圖。

          Show 視圖只是簡(jiǎn)單地輸出了 timestamp 的值,如下所示:

          如果你觀察前面的示例,會(huì)發(fā)現(xiàn)每次你導(dǎo)航至 /Home/Index 的時(shí)候, 都會(huì)有一個(gè)新的 timestamp 被賦值給了緩存項(xiàng)。這是因?yàn)槲覀儾]有對(duì)此進(jìn)行檢查,規(guī)定只有在數(shù)據(jù)項(xiàng)不存在的時(shí)候才賦值。許多時(shí)候你都會(huì)想要這樣做的。這里有兩種辦法可以在 Index() 這個(gè) action 里面來做這樣的檢查。我們把兩種辦法都在下面列了出來

          可以使用 TryGet() 來檢查緩存中是否存在特定的鍵值

          第一種辦法使用了你早先用過的同一個(gè) Get() 方法,這一次它被拿來跟 if 塊一起用。如果 Get() 不能在緩存中找到指定的數(shù)據(jù)項(xiàng),IsNullOrEmpty() 就會(huì)返回 true。而只有這時(shí)候 Set() 才會(huì)被調(diào)用,一次來添加數(shù)據(jù)項(xiàng)。

          第二種辦法更加優(yōu)雅一點(diǎn)。它使用 TryGet() 方法來獲取一個(gè)數(shù)據(jù)項(xiàng)。TryGet() 方法會(huì)返回一個(gè)布爾值來指明數(shù)據(jù)項(xiàng)有沒有被找到。實(shí)際的數(shù)據(jù)項(xiàng)可以使用一個(gè)輸出參數(shù)拉取出來。如果 TryGet() 返回false,Set() 就會(huì)被用來添加數(shù)據(jù)。

          如果不存在的話,可以使用 GetOrCreate() 來添加一項(xiàng)

          有時(shí)你需要從緩存中檢索現(xiàn)有項(xiàng)。如果該項(xiàng)目不存在,則希望添加該項(xiàng)。這兩個(gè)任務(wù) - 如果它存在獲取值,否則創(chuàng)建之 - 可以使用 GetOrCreate() 方法來實(shí)現(xiàn)。修改后的 Show() 方法展示了如何實(shí)現(xiàn)的

          Show() 動(dòng)作現(xiàn)在使用 GetOrCreate() 方法。 GetOrCreate() 方法將檢查時(shí)間戳的鍵值是否存在。如果是,現(xiàn)有值將被賦值給局部變量。否則,將根據(jù)第二個(gè)參數(shù)中指定的邏輯創(chuàng)建一個(gè)新條目并將其添加到緩存中。

          在緩存的數(shù)據(jù)項(xiàng)上面設(shè)置絕對(duì)和滾動(dòng)的過期時(shí)間

          一個(gè)緩存項(xiàng)只要被添加到緩存就會(huì)一直存儲(chǔ),除非它被明確地使用 Remove() 從緩存中移除。你也可以在一個(gè)緩存項(xiàng)上面設(shè)置一個(gè)絕對(duì)和滾動(dòng)的過期時(shí)間。一個(gè)絕對(duì)的過期設(shè)置意味著該緩存項(xiàng)會(huì)在嚴(yán)格指定的日期和時(shí)間點(diǎn)被移除,而滾動(dòng)過期設(shè)置則意味著它在給定的一段時(shí)間量處于空閑狀態(tài)(也就是沒人去訪問)之后被移除。

          為了能在一個(gè)緩存項(xiàng)上面設(shè)置這兩種過期策略,你要用到 MemoryCacheEntryOptions 對(duì)象。如下代碼向你展示了如何去使用。

          上述代碼來自于修改過的 Index() action,它創(chuàng)建了一個(gè) MemoryCacheEntryOptions 的對(duì)象,然后將它的 AbsoluteExpiration 屬性設(shè)置為從此刻到一分鐘之后的一個(gè) DateTime 值,它還將 SlidingExpiration 屬性設(shè)置為一分鐘。這些值都指定了該緩存項(xiàng)會(huì)在一分鐘之后從緩存移除,不管其是否會(huì)被訪問。此外,如果該緩存項(xiàng)如初持續(xù)空閑了有一分鐘,它也會(huì)被從緩存中移除。

          等你將 AbsoluteExpiration 和 SlidingExpiration 的值設(shè)置后, Set() 方法就可以被用來將一個(gè)數(shù)據(jù)項(xiàng)添加到緩存。這一次 MemoryCacheEntryOptions 對(duì)象會(huì)被作為第三個(gè)參數(shù)傳遞給 Set() 方法。

          當(dāng)緩存項(xiàng)會(huì)被移除時(shí),可以連接回調(diào)

          有時(shí)你會(huì)想要在緩存項(xiàng)從緩存中被移除時(shí)收到通知。可能會(huì)有多種原因需要從緩存中移除數(shù)據(jù)項(xiàng)。例如,因?yàn)槊鞔_地執(zhí)行了 Remove() 方法而移除了一個(gè)緩存項(xiàng), 也有可能是因?yàn)樗?AbsoluteExpiration 和 SlidingExpiration 值已經(jīng)到期而被移除,諸如此類的原因。

          為了能知道項(xiàng)目是何時(shí)從緩存移除的,你需要編寫一個(gè)緩存函數(shù)。如下代碼向你展示了如何去做這件事情

          請(qǐng)仔細(xì)觀察這段代碼。 MyCallback() 是 HomeController 類里面的一個(gè)私有靜態(tài)函數(shù),它有四個(gè)參數(shù)。前面兩個(gè)參數(shù)表示剛剛刪除的緩存項(xiàng)的鍵和值,第三個(gè)參數(shù)表示的是該數(shù)據(jù)項(xiàng)被刪除的原因。EvictionReason 是一個(gè)枚舉類型,它維護(hù)者各種可能的刪除原因,如過期,刪除以及替換。

          在回調(diào)函數(shù)的內(nèi)部,我們會(huì)基于刪除的原因構(gòu)造一個(gè)字符串消息。我們想要將此消息設(shè)置成另外一個(gè)緩存項(xiàng)。這樣做的話就需要訪問 HomeController 的緩存對(duì)象,此時(shí)狀態(tài)參數(shù)就可以排上用場(chǎng)了。使用狀態(tài)對(duì)象,你可以對(duì) HomeController 的緩存對(duì)象進(jìn)行控制,并使用 Set() 增加一個(gè) callbackMessage 緩存項(xiàng)。

          你可以通過 Show() 這個(gè) action 來訪問到 callbackMessage,如下所示:

          最后就可以在 Show 視圖中顯示出來了:

          一些建議,像上面提到的設(shè)置緩存數(shù)據(jù)項(xiàng)的過期時(shí)間那塊,如果一個(gè)項(xiàng)目中所有的緩存過期時(shí)間是一致的,我們可以有更簡(jiǎn)單的做法,而不是每個(gè)地方都去寫一堆這個(gè):

          可以在頭部定義一個(gè)共有的

          Cache是自定義的一個(gè)緩存類,其中GetMemoryCacheEntryOptions就是獲取當(dāng)前緩存設(shè)置項(xiàng)的,代碼如下:

          這里面我們將過期時(shí)間放到配置文件中。

          這樣,我們的寫法就可以簡(jiǎn)寫很多,當(dāng)然,剛才提到了是使用的 IMemoryCache 的 Set<T>() 來完成的,所以,這里我們不僅可以傳String,還可以按需傳遞,比如:

          到這里,你已經(jīng)大概知道了MemoryCache 的簡(jiǎn)單使用方式,剩下的就自行研究吧~

          出處:https://www.cnblogs.com/zhangxiaoyong/p/9472637.html 作者:瀟十一郎

          nderer

          這貌似是360瀏覽器專用,兼容360的利器啊,,360默認(rèn)是用IE7去渲染頁面的,不管你的系統(tǒng)裝了多高版本的IE,這種行為真是業(yè)界毒瘤啊。

          "renderer" content="webkit">//默認(rèn)webkit內(nèi)核

          "renderer" content="ie-comp">//默認(rèn)IE兼容模式

          "renderer" content="ie-stand">//默認(rèn)IE標(biāo)準(zhǔn)模式

          Expires (期限)

          說明:指定網(wǎng)頁在緩存中的過期時(shí)間,一旦網(wǎng)頁過期,必須到服務(wù)器上重新調(diào)閱。

          用法:

          注意:必須使用GMT的時(shí)間格式,或直接設(shè)為0(數(shù)字表示多少時(shí)間后過期)。

          Pragma (cach模式)

          說明:禁止瀏覽器從本地機(jī)的緩存中調(diào)閱頁面內(nèi)容。

          用法:

          注意:網(wǎng)頁不保存在緩存中,每次訪問都刷新頁面。這樣設(shè)定,訪問者將無法脫機(jī)瀏覽。

          Set-Cookie (cookie設(shè)定)

          說明:瀏覽器訪問某個(gè)頁面時(shí)會(huì)將它存在緩存中,下次再次訪問時(shí)就可從緩存中讀取,以提高速度。

          當(dāng)你希望訪問者每次都刷新你廣告的圖標(biāo),或每次都刷新你的計(jì)數(shù)器,就要禁用緩存了。

          通常HTML文件沒有必要禁用緩存,對(duì)于ASP等頁面,就可以使用禁用緩存,因?yàn)槊看慰吹降捻撁娑际窃诜?wù)器動(dòng)態(tài)生成的,緩存就失去意義。如果網(wǎng)頁過期,那么存盤的cookie將被刪除。

          Window-target (顯示窗口的設(shè)定)

          說明:強(qiáng)制頁面在當(dāng)前窗口以獨(dú)立頁面顯示。

          用法:

          注意:這個(gè)屬性是用來防止別人在框架里調(diào)用你的頁面。Content選項(xiàng):_blank、_top、_self、_parent

          Pics-label (網(wǎng)頁RSAC等級(jí)評(píng)定)

          說明:在IE的Internet選項(xiàng)中有一項(xiàng)內(nèi)容設(shè)置,可以防止瀏覽一些受限制的網(wǎng)站,而網(wǎng)站的限制級(jí)

          別就是通過該參數(shù)來設(shè)置的。

          用法:I gen comment ‘RSACi North America Sever’ by

          for ‘http://www.microsoft.com’ on ‘1997.06.30T14:21-0500′ r(n0 s0 v0 l0))">

          注意:不要將級(jí)別設(shè)置的太高。RSAC的評(píng)估系統(tǒng)提供了一種用來評(píng)價(jià)Web站點(diǎn)內(nèi)容的標(biāo)準(zhǔn)。

          用戶可以設(shè)置Microsoft Internet Explorer(IE3.0以上)來排除包含有色情和暴力內(nèi)容的站點(diǎn)。

          上面這個(gè)例子中的HTML取自Microsoft的主頁。代碼中的(n 0 s 0 v 0 l 0)表示該站點(diǎn)不包含不健康內(nèi)容。

          級(jí)別的評(píng)定是由RSAC,即美國(guó)娛樂委員會(huì)的評(píng)級(jí)機(jī)構(gòu)評(píng)定的,如果你想進(jìn)一步了解RSAC評(píng)估系統(tǒng)的等級(jí)內(nèi)容,或者你需要評(píng)價(jià)自己的網(wǎng)站,可以訪問RSAC的站點(diǎn):http://www.rsac.org/。

          Content-Script-Type (腳本相關(guān))

          說明:這是近來W3C的規(guī)范,指明頁面中腳本的類型。

          RSS 網(wǎng)站地圖-Sitemap

          復(fù)制代碼保存到一個(gè)sitemap.xml(或者ror.xml)文件中,然后上傳到你應(yīng)用的根目錄下。

          并且把下面代碼增加到你站點(diǎn)主頁的 標(biāo)簽中,主要是為了方便搜索引擎來讀取。

          如果你的站點(diǎn)地圖文件名是ror.xml,記得要把代碼中的href改成href="ror.xml"

          Content-Type和Content-Language (顯示字符集的設(shè)定)

          說明:設(shè)定頁面使用的字符集,用以說明主頁制作所使用的文字已經(jīng)語言,

          瀏覽器會(huì)根據(jù)此來調(diào)用相應(yīng)的字符集顯示page內(nèi)容。

          注意:

          該meta標(biāo)簽定義了HTML頁面所使用的字符集為GB2132,就是國(guó)標(biāo)漢字碼。

          如果將其中的“charset=GB2312"替換成“BIG5",則該頁面所用的字符集就是繁體中文Big5碼。

          當(dāng)你瀏覽一些國(guó)外的站點(diǎn)時(shí),IE瀏覽器會(huì)提示你要正確顯示該頁面需要下載xx語支持。

          這個(gè)功能就是通過讀取HTML頁面meta標(biāo)簽的Content-Type屬性而得知需要使用哪種字符集顯示該頁面的。

          如果系統(tǒng)里沒有裝相應(yīng)的字符集,則IE就提示下載。

          其他的語言也對(duì)應(yīng)不同的charset,比如日文的字符集是“iso-2022-jp ",韓文的是“ks_c_5601"。

          Content-Type的Content還可以是:text/xml等文檔類型;

          Charset選項(xiàng):

          ISO-8859-1(英文)、BIG5、UTF-8、SHIFT-Jis、Euc、Koi8-2、us-ascii,

          x-mac-roman, iso-8859-2, x-mac-ce, iso-2022-jp, x-sjis, x-euc-jp,euc-kr,

          iso-2022-kr, gb2312, gb_2312-80, x-euc-tw, x-cns11643-1,x-cns11643-2等字符集;

          Content-Language的Content還可以是:EN、FR等語言代碼。

          webapp里主要的mate用途

          添加到主屏幕后,全屏顯示。

          這meta的作用就是刪除默認(rèn)的蘋果工具欄和菜單欄。content有兩個(gè)值”yes”和”no”,當(dāng)我們需要顯示工具欄和菜單欄時(shí),這個(gè)行meta就不用加了,默認(rèn)就是顯示。

          默認(rèn)值為default(白色),可以定為black(黑色)和black-translucent(灰色半透明)。

          注意: 若值為“black-translucent”將會(huì)占據(jù)頁面px位置,浮在頁面上方(會(huì)覆蓋頁面20px高度–iphone4和itouch4的Retina屏幕為40px)。

          在iOS中有兩個(gè)meta值,apple-mobile-web-app-capable和apple-mobile-web-app-status-bar-style,這兩個(gè)會(huì)讓網(wǎng)頁內(nèi)容以應(yīng)用程序風(fēng)格顯示,并使?fàn)顟B(tài)欄透明。

          說明: 這個(gè)link就是設(shè)置web app的放置主屏幕上icon文件路徑。

          圖片尺寸可以設(shè)定為57*57(px)或者Retina可以定為114*114(px),ipad尺寸為72*72(px)

          apple-touch-icon

          iOS用rel="apple-touch-icon",android 用rel="apple-touch-icon-precomposed"。這樣就能在用戶把網(wǎng)頁存為書簽時(shí),在手機(jī)HOME界面創(chuàng)建應(yīng)用程序樣式的圖標(biāo)。

          name="sharecontent" data-msg-img="縮略圖地址" data-msg-title="標(biāo)題" data-msg-content="簡(jiǎn)介" data-msg-callBack="" data-line-img="縮略圖地址" data-line-title="標(biāo)題" data-line-callBack=""/>

          ps:

          告訴瀏覽器以什么版本的IE的兼容模式來顯示網(wǎng)頁

          其中最后一行是永遠(yuǎn)以最新的IE版本模式來顯示網(wǎng)頁的。

          另外加上Emulate模式

          Emulate模式后則更重視

          (細(xì)心的人會(huì)注意到,用IE9去訪問帶有x-ua-compatible的頁面時(shí)是不會(huì)出現(xiàn)兼容視圖按鈕的)

          防止所有搜索引擎將網(wǎng)站中的網(wǎng)頁編入索引

          <meta name="robots" content="noindex">

          們知道,在使用瀏覽器的后退和前進(jìn)按鈕時(shí),瀏覽器會(huì)使用緩存來優(yōu)化您的頁面加載過程。它顯著改善了用戶的瀏覽體驗(yàn)——尤其是那些網(wǎng)絡(luò)或設(shè)備較慢的用戶。作為 Web 開發(fā)人員,了解如何在所有瀏覽器中針對(duì)這種緩存優(yōu)化頁面至關(guān)重要,這樣您的用戶才能獲得收益。

          回退前進(jìn)緩存是一種內(nèi)存緩存,用于在用戶導(dǎo)航離開時(shí)存儲(chǔ)頁面(包括 JavaScript 堆)的完整快照。 整個(gè)頁面都在內(nèi)存中,如果用戶決定返回,瀏覽器可以快速輕松地恢復(fù)它。比如當(dāng)點(diǎn)擊返回時(shí),在那一刻,該緩存可以對(duì)上一個(gè)頁面的加載速度產(chǎn)生很大的影響:

          下面是有緩存和沒緩存的加載回退頁面的過程:

          • 無緩存:發(fā)起一個(gè)新請(qǐng)求以加載前一個(gè)頁面,并且根據(jù)該頁面針對(duì)重復(fù)訪問的優(yōu)化程度,瀏覽器可能必須重新下載、重新解析和重新執(zhí)行部分(或全部)它剛剛下載的資源。
          • 有緩存:加載本質(zhì)上是即時(shí)的,因?yàn)檎麄€(gè)頁面都可以從內(nèi)存中恢復(fù),根本不用去網(wǎng)絡(luò)

          回退前進(jìn)緩存是如何工作的

          回退前進(jìn)緩存使用的“緩存”不同于 HTTP 緩存(它對(duì)于加快重復(fù)導(dǎo)航也很有用)。 回退前進(jìn)緩存是在內(nèi)存緩存中整個(gè)頁面的快照(包括 JavaScript 堆),而 HTTP 緩存僅包含對(duì)先前發(fā)出的請(qǐng)求的響應(yīng)。由于加載頁面所需的所有請(qǐng)求都可以從 HTTP 緩存中完成是非常罕見的,因此使用回退前進(jìn)緩存恢復(fù)的重復(fù)訪問總是比優(yōu)化得最好的回退前進(jìn)緩存導(dǎo)航更快。

          然而,在內(nèi)存中創(chuàng)建頁面快照涉及到如何最好地保存正在進(jìn)行的代碼方面的一些復(fù)雜性。例如,當(dāng)頁面在回退前進(jìn)緩存中時(shí),如何處理超時(shí)的 setTimeout() 調(diào)用?

          答案是瀏覽器暫停運(yùn)行任何掛起的計(jì)時(shí)器或未解決的Promise——就是說會(huì)掛起所有任務(wù)隊(duì)列中的任務(wù)——并在當(dāng)從回退前進(jìn)緩存恢復(fù)頁面時(shí)恢復(fù)處理任務(wù)。

          在某些情況下,這是相當(dāng)?shù)偷娘L(fēng)險(xiǎn)(例如,setTimeout或Promise),但在其他情況下,它可能會(huì)導(dǎo)致非常混亂或意外的行為。例如,如果瀏覽器暫停了作為 IndexedDB 事務(wù)的一部分所需的任務(wù),它可能會(huì)影響同一源中的其他打開的選項(xiàng)卡(因?yàn)槎鄠€(gè)選項(xiàng)卡可以同時(shí)訪問相同的 IndexedDB 數(shù)據(jù)庫)。因此,瀏覽器通常不會(huì)嘗試在 IndexedDB 事務(wù)的中間緩存頁面或使用可能影響其他頁面的 API。

          可以觀察回退前進(jìn)緩存的API

          雖然回退前進(jìn)緩存是瀏覽器自動(dòng)進(jìn)行的優(yōu)化,但對(duì)于開發(fā)人員來說,知道它何時(shí)發(fā)生仍然很重要,這樣他們就可以優(yōu)化他們的頁面并相應(yīng)地調(diào)整任何指標(biāo)或性能測(cè)量。

          用于觀察回退前進(jìn)緩存的主要事件是頁面轉(zhuǎn)換事件——pageshowpagehide——它們?cè)?strong>回退前進(jìn)緩存存在的時(shí)候就已經(jīng)存在,并且在當(dāng)今使用的幾乎所有瀏覽器中都得到了支持。較新的頁面生命周期事件(freeze和resume)也會(huì)在頁面進(jìn)出回退前進(jìn)緩存時(shí)以及在某些其他情況下調(diào)度。

          觀察何時(shí)從回退前進(jìn)緩存恢復(fù)頁面:

          pageshow 事件在頁面初始加載時(shí)以及頁面從緩存恢復(fù)時(shí)的 load 事件之后立即觸發(fā)。 pageshow 事件有一個(gè)persisted屬性,如果頁面從緩存恢復(fù),則該屬性為 true(如果不是,則為 false)。 您可以使用持久化屬性來區(qū)分常規(guī)頁面加載和緩存恢復(fù)。 例如:

          觀察頁面什么時(shí)候進(jìn)入回退前進(jìn)緩存

          pagehide 是 pageshow 事件的對(duì)應(yīng)事件。 pageshow 事件在頁面正常加載或從緩存恢復(fù)時(shí)觸發(fā)。 pagehide 事件在頁面正常卸載或?yàn)g覽器嘗試將其放入緩存時(shí)觸發(fā)。

          pagehide 事件也有一個(gè)persisted屬性,如果它是假的,那么你可以確信頁面不會(huì)進(jìn)入回退前進(jìn)緩存。 但是,如果persisted 屬性為真,則不能保證頁面會(huì)被緩存。 這意味著瀏覽器打算緩存該頁面,但可能存在無法緩存的因素。下面會(huì)解釋幾種原因,導(dǎo)致它可能仍然不能進(jìn)入緩存并被丟棄。

          為回退前進(jìn)緩存優(yōu)化你的頁面

          并非所有頁面都存儲(chǔ)在回退前進(jìn)緩存中,即使頁面確實(shí)存儲(chǔ)在那里,它也不會(huì)無限期地留在那里。 開發(fā)人員必須了解是什么使頁面符合(和不符合)使用緩存的條件,以最大限度地提高其緩存命中率。以下部分概述了使瀏覽器盡可能緩存您的頁面的最佳實(shí)踐。

          不要使用 unload 事件

          在所有瀏覽器中優(yōu)化回退前進(jìn)緩存的最重要方法是永遠(yuǎn)不要使用 unload 事件。

          unload 事件對(duì)瀏覽器來說是有問題的在 unload 事件觸發(fā)后頁面將不會(huì)繼續(xù)存在。這提出了一個(gè)挑戰(zhàn),因?yàn)槠渲性S多頁面也是在假設(shè)用戶導(dǎo)航離開時(shí)會(huì)觸發(fā) unload 事件的假設(shè)下構(gòu)建的,這不再是真的(并且很長(zhǎng)一段時(shí)間都不是真的)。所以瀏覽器面臨兩難境地,他們必須在可以改善用戶體驗(yàn)的東西之間做出選擇——但也可能會(huì)冒著破壞頁面的風(fēng)險(xiǎn)。

          如果 Chrome 和 Firefox 添加了卸載偵聽器,則選擇使頁面不符合回退前進(jìn)緩存的條件,這樣風(fēng)險(xiǎn)較小,但也會(huì)取消許多頁面被緩存的資格。 Safari 將嘗試使用 unload 事件偵聽器緩存某些頁面,但為了減少潛在的損壞,它不會(huì)在用戶導(dǎo)航離開時(shí)運(yùn)行 unload 事件,這使得該事件非常不可靠。

          不要使用 unload 事件,而是使用 pagehide 事件。 pagehide 事件在當(dāng)前觸發(fā) unload 事件的所有情況下觸發(fā),并且當(dāng)頁面放入回退前進(jìn)緩存時(shí)也會(huì)觸發(fā)。

          事實(shí)上,Lighthouse v6.2.0 添加了一個(gè) no-unload-listeners 審計(jì),如果他們的頁面上的任何 JavaScript(包括來自第三方庫的 JavaScript)添加了 unload 事件監(jiān)聽器,它將警告開發(fā)人員。

          正確的做法:

          避免 window.opener 引用

          在某些瀏覽器(包括基于 Chromium 的瀏覽器)中,如果頁面是使用 window.open() 或(在 88 版之前基于 Chromium 的瀏覽器中)從帶有 target=_blank 的鏈接打開的——沒有指定 rel="noopener"——那么 打開頁面將引用打開頁面的窗口對(duì)象。

          除了存在安全風(fēng)險(xiǎn)之外,具有非空 window.opener 引用的頁面不能安全地放入緩存,因?yàn)檫@可能會(huì)破壞任何試圖訪問它的頁面。

          因此,最好盡可能避免使用 rel="noopener" 創(chuàng)建 window.opener 引用。 如果您的站點(diǎn)需要打開一個(gè)窗口并通過 window.postMessage() 或直接引用 window 對(duì)象來控制它,則打開的窗口和打開器都沒有資格使用緩存。

          始終在用戶導(dǎo)航離開之前關(guān)閉打開的連接

          如上所述,當(dāng)頁面被放入緩存時(shí),所有計(jì)劃的 JavaScript 任務(wù)都會(huì)暫停,然后在頁面從緩存中取出時(shí)恢復(fù)。如果這些計(jì)劃好的 JavaScript 任務(wù)僅訪問 DOM API(或僅與當(dāng)前頁面隔離的其他 API),那么在頁面對(duì)用戶不可見時(shí)暫停這些任務(wù)不會(huì)導(dǎo)致任何問題。

          但是,如果這些任務(wù)連接到的 API 也可以從同一來源的其他頁面訪問(例如:IndexedDB、Web Locks、WebSockets 等),這可能會(huì)出現(xiàn)問題,因?yàn)闀和_@些任務(wù)可能會(huì)阻止其他選項(xiàng)卡中的代碼運(yùn)行.

          因此,某些瀏覽器在以下情況下不會(huì)嘗試將頁面放入緩存

          • 具有打開 IndexedDB 連接的頁面
          • 正在進(jìn)行 fetch() 或 XMLHttpRequest 的頁面
          • 具有打開的 WebSocket 或 WebRTC 連接的頁面

          如果您的頁面使用這些 API 中的任何一個(gè),最好在 pagehide 或 freeze 事件期間始終關(guān)閉連接并刪除或斷開觀察者。這將允許瀏覽器安全地緩存頁面,而不會(huì)影響其他打開的選項(xiàng)卡。然后,如果頁面從緩存恢復(fù),您可以重新打開或重新連接到這些 API(在 pageshow 或 resume 事件中)。

          以下示例顯示了如何在使用 IndexedDB 時(shí)通過關(guān)閉 pagehide 事件偵聽器中的打開連接來確保您的頁面符合緩存條件:

          緩存恢復(fù)后更新陳舊或敏感數(shù)據(jù)

          如果您的站點(diǎn)保留用戶狀態(tài)(尤其是任何敏感的用戶信息),則需要在從回退前進(jìn)緩存恢復(fù)頁面后更新或清除該數(shù)據(jù)。例如,如果用戶導(dǎo)航到結(jié)帳頁面然后更新他們的購物車,如果從緩存恢復(fù)過時(shí)的頁面,則返回導(dǎo)航可能會(huì)顯示過時(shí)的信息。

          另一個(gè)更關(guān)鍵的示例是,如果用戶在公共計(jì)算機(jī)上退出站點(diǎn),并且下一個(gè)用戶單擊后退按鈕。 這可能會(huì)暴露用戶在注銷時(shí)認(rèn)為已清除的私人數(shù)據(jù)。為避免此類情況,如果 event.persisted 為 true,則最好在 pageshow 事件之后始終更新頁面。

          以下代碼檢查 pageshow 事件中是否存在特定于站點(diǎn)的 cookie,如果未找到 cookie,則重新加載:

          測(cè)試一下保證你的頁面會(huì)被緩存

          Chrome DevTools 可以幫助您測(cè)試您的頁面,以確保它們針對(duì)回退前進(jìn)緩存進(jìn)行了優(yōu)化,并確定可能阻止它們符合條件的任何問題。

          要測(cè)試特定頁面,請(qǐng)?jiān)?Chrome 中導(dǎo)航到該頁面,然后在 DevTools 中轉(zhuǎn)到 Application > Back-forward Cache。 接下來單擊 Run Test 按鈕,DevTools 將嘗試導(dǎo)航并返回以確定頁面是否可以從回退前進(jìn)緩存恢復(fù)。

          如果成功,則會(huì)顯示從緩存恢復(fù)成功,失敗也有提示,并告訴你原因。

          成功

          比如百度使用了unload導(dǎo)致緩存失敗 :)

          結(jié)語:

          回退前進(jìn)緩存對(duì)提高性能,及用戶體驗(yàn)很有幫助。大家要寫正確的代碼來使自己的頁面盡量被緩存,這樣你們的網(wǎng)站才能大大獲益。


          主站蜘蛛池模板: 色婷婷香蕉在线一区二区| 成人免费视频一区| 97精品一区二区视频在线观看 | 大帝AV在线一区二区三区| 午夜福利国产一区二区| 色噜噜狠狠一区二区三区果冻 | 熟女精品视频一区二区三区| 国产产一区二区三区久久毛片国语| 亚洲国产精品无码久久一区二区| 日本美女一区二区三区| 精品国产福利在线观看一区| ...91久久精品一区二区三区 | 欧美成人aaa片一区国产精品 | 国产AV午夜精品一区二区三区| 国产av福利一区二区三巨| 日本一区二区三区不卡在线视频| 射精专区一区二区朝鲜| 精品一区二区久久久久久久网站| 久久一区二区免费播放| 国产精品污WWW一区二区三区| 国产在线一区观看| 国产精品一区二区久久沈樵| 一区二区无码免费视频网站| 国产成人精品日本亚洲专一区 | 精品国产免费一区二区| 亚洲av无码片vr一区二区三区| 国产美女一区二区三区| 一本一道波多野结衣一区| 日韩免费一区二区三区在线| 国产精品视频一区麻豆| 中文乱码人妻系列一区二区 | 精品国产一区二区三区久久狼 | 亚洲国产视频一区| 毛片一区二区三区| 日韩美一区二区三区| 一区二区中文字幕在线观看| 国产精品 视频一区 二区三区| 激情内射亚州一区二区三区爱妻| 国产成人无码AV一区二区| 制服中文字幕一区二区| 久久久久无码国产精品一区|