对于缓存我们都已经很熟悉了,缓存分为很多种,浏览器缓存、试图缓存、服务器缓存、数据库缓存等等一些,那今天我们先介绍一下视图缓存和MemoryCache内存缓存的概念和用法:
在老的版本的MVC里面,有一种可以缓存视图的特性(OutputCache),可以保持同一个参数的请求,在N段时间内,直接从mvc的缓存中读取,不去走视图的逻辑。
在Asp.Net core 2.1中,官方文档上称:响应缓存可减少客户端或代理对 web 服务器的请求数。 响应缓存还可减少量工作的 web 服务器执行程序生成响应。 响应缓存由标头,指定你希望客户端、 代理和缓存响应的中间件如何控制。
在Asp.Net Core 2.1 中,没有了OutputCache,换成了ResponseCache,ResponseCache必须带一个参数:Duration 单位为秒,最少设置一秒钟
然后再浏览器请求这个视图
在浏览器的响应头的Cache-Control 中出现max-age=5, Http协议对此的解释是
客户端将不会接受其保留时间大于指定的秒数的响应。 示例: max-age=60 (60 秒), max-age=2592000 (1 个月)
如果在浏览器中禁用缓存,那么ResponseCache不会有任何效果
Vary过滤
关于vary在Http响应头的作用就是:告诉缓存服务器或者CDN,我还是同一个浏览器的请求,你给我缓存就行了,如果你换个浏览器去请求,那么vary的值肯定为空,那么缓存服务器就会认为你是一个新的请求,就会去读取最新的数据给浏览器
参考资料:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
在Http中 :no-store,请求和响应的信息都不应该被存储在对方的磁盘系统中
ResponseCacheLocation.None是在Cache-Control设置一个no-cache属性,让浏览器不缓存当前这个URL
缓存配置(CacheProfiles)
在一个正常的项目中,肯定有很多个控制器,但是不可能每个控制器的缓存策略都一样,这时候,我们就需要一个缓存的配置来灵活应对这个问题
在mvc的服务注入的时候,我们可以在option里面注入进我们的缓存策略
然后我们在使用的时候,直接使用配置策略的名称就好了
这样我们就能和之前在特性后边配置一样了,这是视图缓存,下面我们就来看看MemoryCache 是个什么东东
如果回到老版本的.NET,说到内存缓存大家可能立马想到了HttpRuntime.Cache,它位于System.Web命名空间下,但是在ASP.NET Core中System.Web已经不复存在。今儿个就简单的聊聊如何在ASP.NET Core中使用内存缓存
有几个问题我们需要先进行了解:
1.什么时候需要用到缓存?
一般将经常访问但是又不是经常改变的数据放进缓存是再好不过了,这样可以明显提高应用程序的性能。
2.缓存的好处?
建议百度
不同于 ASP.NET Web 窗体和 ASP.NET MVC,ASP.NET Core 没有内置的 Cache 对象,可以拿来在控制器里面直接使用。 这里,内存缓存时通过依赖注入来启用的,因此第一步就是在 Startup 类中注册内存缓存的服务。如此,就得打开 Startup 类然后定位到 ConfigureServices() 方法,像下面这样修改 ConfigureServices() 方法:
①首先需要在ConfigureServices中注册缓存服务
services.AddMemoryCache()
为了向你的应用程序加入内存缓存能力,你需要在服务集合上调用 AddMemoryCache() 方法。采用这种办法就可以让一个内存缓存(它是一个 IMemoryCache 对象)的默认实现可以被注入到控制器中去。
②在下面的代码中从Home控制器的构造函中获取IMemoryCache实例(内存缓存使用依赖注入来注入缓存对象)
如你所见,上述代码声明了一个 ImemoryCache 的私有变量。该变量会被构造器中被赋值。构造器会通过 DI(依赖注入)接收到缓存参数,然后被存储在本地变量总,提供后续使用。
③关于缓存的使用常用的就是Set Get Remove,一般有以下几种做法可以参考:
⑴可以使用 Set() 方法来在缓存中存东西
等你有了这个 IMemoryCache 对象,就可以读取或者向它写入数据了。向缓存写入数据项是相当直接的
上述代码在 Index() 这个 action 中设置了一个缓存项。这是通过使用 IMemoryCache 的 Set<T>() 来完成的。Set() 方法的第一个参数是键名,用来标识该数据项。第二个参数是键的取值。在此例中,我们存储一个字符串的键和一个字符串的值,而你也可以存储其它类型 (原生以及自定义的类型) 的键值对。
⑵可以使用 Get 方法来从缓存中获取到一个数据项
等你向缓存中添加好了数据,也许会想要在应用程序的其它地方去获取到该数据,可以用 Get() 来做到。如下代码会告诉你如何来做这件事情。
上述代码从 HomeController 的另外一个action(Show)那里获取到了一个缓存的数据项。Get() 方法会指定数据项的类型以及它的键名。如果该数据项存在的话,就会被返回并且被赋值给 timestamp 这个字符串变量。然后这个 timestamp 的值就会被传递给 Show 视图。
Show 视图只是简单地输出了 timestamp 的值,如下所示:
如果你观察前面的示例,会发现每次你导航至 /Home/Index 的时候, 都会有一个新的 timestamp 被赋值给了缓存项。这是因为我们并没有对此进行检查,规定只有在数据项不存在的时候才赋值。许多时候你都会想要这样做的。这里有两种办法可以在 Index() 这个 action 里面来做这样的检查。我们把两种办法都在下面列了出来
可以使用 TryGet() 来检查缓存中是否存在特定的键值
第一种办法使用了你早先用过的同一个 Get() 方法,这一次它被拿来跟 if 块一起用。如果 Get() 不能在缓存中找到指定的数据项,IsNullOrEmpty() 就会返回 true。而只有这时候 Set() 才会被调用,一次来添加数据项。
第二种办法更加优雅一点。它使用 TryGet() 方法来获取一个数据项。TryGet() 方法会返回一个布尔值来指明数据项有没有被找到。实际的数据项可以使用一个输出参数拉取出来。如果 TryGet() 返回false,Set() 就会被用来添加数据。
如果不存在的话,可以使用 GetOrCreate() 来添加一项
有时你需要从缓存中检索现有项。如果该项目不存在,则希望添加该项。这两个任务 - 如果它存在获取值,否则创建之 - 可以使用 GetOrCreate() 方法来实现。修改后的 Show() 方法展示了如何实现的
Show() 动作现在使用 GetOrCreate() 方法。 GetOrCreate() 方法将检查时间戳的键值是否存在。如果是,现有值将被赋值给局部变量。否则,将根据第二个参数中指定的逻辑创建一个新条目并将其添加到缓存中。
在缓存的数据项上面设置绝对和滚动的过期时间
一个缓存项只要被添加到缓存就会一直存储,除非它被明确地使用 Remove() 从缓存中移除。你也可以在一个缓存项上面设置一个绝对和滚动的过期时间。一个绝对的过期设置意味着该缓存项会在严格指定的日期和时间点被移除,而滚动过期设置则意味着它在给定的一段时间量处于空闲状态(也就是没人去访问)之后被移除。
为了能在一个缓存项上面设置这两种过期策略,你要用到 MemoryCacheEntryOptions 对象。如下代码向你展示了如何去使用。
上述代码来自于修改过的 Index() action,它创建了一个 MemoryCacheEntryOptions 的对象,然后将它的 AbsoluteExpiration 属性设置为从此刻到一分钟之后的一个 DateTime 值,它还将 SlidingExpiration 属性设置为一分钟。这些值都指定了该缓存项会在一分钟之后从缓存移除,不管其是否会被访问。此外,如果该缓存项如初持续空闲了有一分钟,它也会被从缓存中移除。
等你将 AbsoluteExpiration 和 SlidingExpiration 的值设置后, Set() 方法就可以被用来将一个数据项添加到缓存。这一次 MemoryCacheEntryOptions 对象会被作为第三个参数传递给 Set() 方法。
当缓存项会被移除时,可以连接回调
有时你会想要在缓存项从缓存中被移除时收到通知。可能会有多种原因需要从缓存中移除数据项。例如,因为明确地执行了 Remove() 方法而移除了一个缓存项, 也有可能是因为它的 AbsoluteExpiration 和 SlidingExpiration 值已经到期而被移除,诸如此类的原因。
为了能知道项目是何时从缓存移除的,你需要编写一个缓存函数。如下代码向你展示了如何去做这件事情
请仔细观察这段代码。 MyCallback() 是 HomeController 类里面的一个私有静态函数,它有四个参数。前面两个参数表示刚刚删除的缓存项的键和值,第三个参数表示的是该数据项被删除的原因。EvictionReason 是一个枚举类型,它维护者各种可能的删除原因,如过期,删除以及替换。
在回调函数的内部,我们会基于删除的原因构造一个字符串消息。我们想要将此消息设置成另外一个缓存项。这样做的话就需要访问 HomeController 的缓存对象,此时状态参数就可以排上用场了。使用状态对象,你可以对 HomeController 的缓存对象进行控制,并使用 Set() 增加一个 callbackMessage 缓存项。
你可以通过 Show() 这个 action 来访问到 callbackMessage,如下所示:
最后就可以在 Show 视图中显示出来了:
一些建议,像上面提到的设置缓存数据项的过期时间那块,如果一个项目中所有的缓存过期时间是一致的,我们可以有更简单的做法,而不是每个地方都去写一堆这个:
可以在头部定义一个共有的
Cache是自定义的一个缓存类,其中GetMemoryCacheEntryOptions就是获取当前缓存设置项的,代码如下:
这里面我们将过期时间放到配置文件中。
这样,我们的写法就可以简写很多,当然,刚才提到了是使用的 IMemoryCache 的 Set<T>() 来完成的,所以,这里我们不仅可以传String,还可以按需传递,比如:
到这里,你已经大概知道了MemoryCache 的简单使用方式,剩下的就自行研究吧~
出处:https://www.cnblogs.com/zhangxiaoyong/p/9472637.html 作者:潇十一郎
nderer
这貌似是360浏览器专用,兼容360的利器啊,,360默认是用IE7去渲染页面的,不管你的系统装了多高版本的IE,这种行为真是业界毒瘤啊。
"renderer" content="webkit">//默认webkit内核
"renderer" content="ie-comp">//默认IE兼容模式
"renderer" content="ie-stand">//默认IE标准模式
Expires (期限)
说明:指定网页在缓存中的过期时间,一旦网页过期,必须到服务器上重新调阅。
用法:
注意:必须使用GMT的时间格式,或直接设为0(数字表示多少时间后过期)。
Pragma (cach模式)
说明:禁止浏览器从本地机的缓存中调阅页面内容。
用法:
注意:网页不保存在缓存中,每次访问都刷新页面。这样设定,访问者将无法脱机浏览。
Set-Cookie (cookie设定)
说明:浏览器访问某个页面时会将它存在缓存中,下次再次访问时就可从缓存中读取,以提高速度。
当你希望访问者每次都刷新你广告的图标,或每次都刷新你的计数器,就要禁用缓存了。
通常HTML文件没有必要禁用缓存,对于ASP等页面,就可以使用禁用缓存,因为每次看到的页面都是在服务器动态生成的,缓存就失去意义。如果网页过期,那么存盘的cookie将被删除。
Window-target (显示窗口的设定)
说明:强制页面在当前窗口以独立页面显示。
用法:
注意:这个属性是用来防止别人在框架里调用你的页面。Content选项:_blank、_top、_self、_parent
Pics-label (网页RSAC等级评定)
说明:在IE的Internet选项中有一项内容设置,可以防止浏览一些受限制的网站,而网站的限制级
别就是通过该参数来设置的。
用法:I gen comment ‘RSACi North America Sever’ by
for ‘http://www.microsoft.com’ on ‘1997.06.30T14:21-0500′ r(n0 s0 v0 l0))">
注意:不要将级别设置的太高。RSAC的评估系统提供了一种用来评价Web站点内容的标准。
用户可以设置Microsoft Internet Explorer(IE3.0以上)来排除包含有色情和暴力内容的站点。
上面这个例子中的HTML取自Microsoft的主页。代码中的(n 0 s 0 v 0 l 0)表示该站点不包含不健康内容。
级别的评定是由RSAC,即美国娱乐委员会的评级机构评定的,如果你想进一步了解RSAC评估系统的等级内容,或者你需要评价自己的网站,可以访问RSAC的站点:http://www.rsac.org/。
Content-Script-Type (脚本相关)
说明:这是近来W3C的规范,指明页面中脚本的类型。
RSS 网站地图-Sitemap
复制代码保存到一个sitemap.xml(或者ror.xml)文件中,然后上传到你应用的根目录下。
并且把下面代码增加到你站点主页的 标签中,主要是为了方便搜索引擎来读取。
如果你的站点地图文件名是ror.xml,记得要把代码中的href改成href="ror.xml"
Content-Type和Content-Language (显示字符集的设定)
说明:设定页面使用的字符集,用以说明主页制作所使用的文字已经语言,
浏览器会根据此来调用相应的字符集显示page内容。
注意:
该meta标签定义了HTML页面所使用的字符集为GB2132,就是国标汉字码。
如果将其中的“charset=GB2312"替换成“BIG5",则该页面所用的字符集就是繁体中文Big5码。
当你浏览一些国外的站点时,IE浏览器会提示你要正确显示该页面需要下载xx语支持。
这个功能就是通过读取HTML页面meta标签的Content-Type属性而得知需要使用哪种字符集显示该页面的。
如果系统里没有装相应的字符集,则IE就提示下载。
其他的语言也对应不同的charset,比如日文的字符集是“iso-2022-jp ",韩文的是“ks_c_5601"。
Content-Type的Content还可以是:text/xml等文档类型;
Charset选项:
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的作用就是删除默认的苹果工具栏和菜单栏。content有两个值”yes”和”no”,当我们需要显示工具栏和菜单栏时,这个行meta就不用加了,默认就是显示。
默认值为default(白色),可以定为black(黑色)和black-translucent(灰色半透明)。
注意: 若值为“black-translucent”将会占据页面px位置,浮在页面上方(会覆盖页面20px高度–iphone4和itouch4的Retina屏幕为40px)。
在iOS中有两个meta值,apple-mobile-web-app-capable和apple-mobile-web-app-status-bar-style,这两个会让网页内容以应用程序风格显示,并使状态栏透明。
说明: 这个link就是设置web app的放置主屏幕上icon文件路径。
图片尺寸可以设定为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"。这样就能在用户把网页存为书签时,在手机HOME界面创建应用程序样式的图标。
name="sharecontent" data-msg-img="缩略图地址" data-msg-title="标题" data-msg-content="简介" data-msg-callBack="" data-line-img="缩略图地址" data-line-title="标题" data-line-callBack=""/>
ps:
告诉浏览器以什么版本的IE的兼容模式来显示网页
其中最后一行是永远以最新的IE版本模式来显示网页的。
另外加上Emulate模式
Emulate模式后则更重视
(细心的人会注意到,用IE9去访问带有x-ua-compatible的页面时是不会出现兼容视图按钮的)
防止所有搜索引擎将网站中的网页编入索引
<meta name="robots" content="noindex">
们知道,在使用浏览器的后退和前进按钮时,浏览器会使用缓存来优化您的页面加载过程。它显着改善了用户的浏览体验——尤其是那些网络或设备较慢的用户。作为 Web 开发人员,了解如何在所有浏览器中针对这种缓存优化页面至关重要,这样您的用户才能获得收益。
回退前进缓存是一种内存缓存,用于在用户导航离开时存储页面(包括 JavaScript 堆)的完整快照。 整个页面都在内存中,如果用户决定返回,浏览器可以快速轻松地恢复它。比如当点击返回时,在那一刻,该缓存可以对上一个页面的加载速度产生很大的影响:
下面是有缓存和没缓存的加载回退页面的过程:
回退前进缓存是如何工作的
回退前进缓存使用的“缓存”不同于 HTTP 缓存(它对于加快重复导航也很有用)。 回退前进缓存是在内存缓存中整个页面的快照(包括 JavaScript 堆),而 HTTP 缓存仅包含对先前发出的请求的响应。由于加载页面所需的所有请求都可以从 HTTP 缓存中完成是非常罕见的,因此使用回退前进缓存恢复的重复访问总是比优化得最好的非回退前进缓存导航更快。
然而,在内存中创建页面快照涉及到如何最好地保存正在进行的代码方面的一些复杂性。例如,当页面在回退前进缓存中时,如何处理超时的 setTimeout() 调用?
答案是浏览器暂停运行任何挂起的计时器或未解决的Promise——就是说会挂起所有任务队列中的任务——并在当从回退前进缓存恢复页面时恢复处理任务。
在某些情况下,这是相当低的风险(例如,setTimeout或Promise),但在其他情况下,它可能会导致非常混乱或意外的行为。例如,如果浏览器暂停了作为 IndexedDB 事务的一部分所需的任务,它可能会影响同一源中的其他打开的选项卡(因为多个选项卡可以同时访问相同的 IndexedDB 数据库)。因此,浏览器通常不会尝试在 IndexedDB 事务的中间缓存页面或使用可能影响其他页面的 API。
可以观察回退前进缓存的API
虽然回退前进缓存是浏览器自动进行的优化,但对于开发人员来说,知道它何时发生仍然很重要,这样他们就可以优化他们的页面并相应地调整任何指标或性能测量。
用于观察回退前进缓存的主要事件是页面转换事件——pageshow 和 pagehide——它们在回退前进缓存存在的时候就已经存在,并且在当今使用的几乎所有浏览器中都得到了支持。较新的页面生命周期事件(freeze和resume)也会在页面进出回退前进缓存时以及在某些其他情况下调度。
观察何时从回退前进缓存恢复页面:
pageshow 事件在页面初始加载时以及页面从缓存恢复时的 load 事件之后立即触发。 pageshow 事件有一个persisted属性,如果页面从缓存恢复,则该属性为 true(如果不是,则为 false)。 您可以使用持久化属性来区分常规页面加载和缓存恢复。 例如:
观察页面什么时候进入回退前进缓存
pagehide 是 pageshow 事件的对应事件。 pageshow 事件在页面正常加载或从缓存恢复时触发。 pagehide 事件在页面正常卸载或浏览器尝试将其放入缓存时触发。
pagehide 事件也有一个persisted属性,如果它是假的,那么你可以确信页面不会进入回退前进缓存。 但是,如果persisted 属性为真,则不能保证页面会被缓存。 这意味着浏览器打算缓存该页面,但可能存在无法缓存的因素。下面会解释几种原因,导致它可能仍然不能进入缓存并被丢弃。
为回退前进缓存优化你的页面
并非所有页面都存储在回退前进缓存中,即使页面确实存储在那里,它也不会无限期地留在那里。 开发人员必须了解是什么使页面符合(和不符合)使用缓存的条件,以最大限度地提高其缓存命中率。以下部分概述了使浏览器尽可能缓存您的页面的最佳实践。
不要使用 unload 事件
在所有浏览器中优化回退前进缓存的最重要方法是永远不要使用 unload 事件。
unload 事件对浏览器来说是有问题的,在 unload 事件触发后页面将不会继续存在。这提出了一个挑战,因为其中许多页面也是在假设用户导航离开时会触发 unload 事件的假设下构建的,这不再是真的(并且很长一段时间都不是真的)。所以浏览器面临两难境地,他们必须在可以改善用户体验的东西之间做出选择——但也可能会冒着破坏页面的风险。
如果 Chrome 和 Firefox 添加了卸载侦听器,则选择使页面不符合回退前进缓存的条件,这样风险较小,但也会取消许多页面被缓存的资格。 Safari 将尝试使用 unload 事件侦听器缓存某些页面,但为了减少潜在的损坏,它不会在用户导航离开时运行 unload 事件,这使得该事件非常不可靠。
不要使用 unload 事件,而是使用 pagehide 事件。 pagehide 事件在当前触发 unload 事件的所有情况下触发,并且当页面放入回退前进缓存时也会触发。
事实上,Lighthouse v6.2.0 添加了一个 no-unload-listeners 审计,如果他们的页面上的任何 JavaScript(包括来自第三方库的 JavaScript)添加了 unload 事件监听器,它将警告开发人员。
正确的做法:
避免 window.opener 引用
在某些浏览器(包括基于 Chromium 的浏览器)中,如果页面是使用 window.open() 或(在 88 版之前基于 Chromium 的浏览器中)从带有 target=_blank 的链接打开的——没有指定 rel="noopener"——那么 打开页面将引用打开页面的窗口对象。
除了存在安全风险之外,具有非空 window.opener 引用的页面不能安全地放入缓存,因为这可能会破坏任何试图访问它的页面。
因此,最好尽可能避免使用 rel="noopener" 创建 window.opener 引用。 如果您的站点需要打开一个窗口并通过 window.postMessage() 或直接引用 window 对象来控制它,则打开的窗口和打开器都没有资格使用缓存。
始终在用户导航离开之前关闭打开的连接
如上所述,当页面被放入缓存时,所有计划的 JavaScript 任务都会暂停,然后在页面从缓存中取出时恢复。如果这些计划好的 JavaScript 任务仅访问 DOM API(或仅与当前页面隔离的其他 API),那么在页面对用户不可见时暂停这些任务不会导致任何问题。
但是,如果这些任务连接到的 API 也可以从同一来源的其他页面访问(例如:IndexedDB、Web Locks、WebSockets 等),这可能会出现问题,因为暂停这些任务可能会阻止其他选项卡中的代码运行.
因此,某些浏览器在以下情况下不会尝试将页面放入缓存:
如果您的页面使用这些 API 中的任何一个,最好在 pagehide 或 freeze 事件期间始终关闭连接并删除或断开观察者。这将允许浏览器安全地缓存页面,而不会影响其他打开的选项卡。然后,如果页面从缓存恢复,您可以重新打开或重新连接到这些 API(在 pageshow 或 resume 事件中)。
以下示例显示了如何在使用 IndexedDB 时通过关闭 pagehide 事件侦听器中的打开连接来确保您的页面符合缓存条件:
缓存恢复后更新陈旧或敏感数据
如果您的站点保留用户状态(尤其是任何敏感的用户信息),则需要在从回退前进缓存恢复页面后更新或清除该数据。例如,如果用户导航到结帐页面然后更新他们的购物车,如果从缓存恢复过时的页面,则返回导航可能会显示过时的信息。
另一个更关键的示例是,如果用户在公共计算机上退出站点,并且下一个用户单击后退按钮。 这可能会暴露用户在注销时认为已清除的私人数据。为避免此类情况,如果 event.persisted 为 true,则最好在 pageshow 事件之后始终更新页面。
以下代码检查 pageshow 事件中是否存在特定于站点的 cookie,如果未找到 cookie,则重新加载:
测试一下保证你的页面会被缓存
Chrome DevTools 可以帮助您测试您的页面,以确保它们针对回退前进缓存进行了优化,并确定可能阻止它们符合条件的任何问题。
要测试特定页面,请在 Chrome 中导航到该页面,然后在 DevTools 中转到 Application > Back-forward Cache。 接下来单击 Run Test 按钮,DevTools 将尝试导航并返回以确定页面是否可以从回退前进缓存恢复。
如果成功,则会显示从缓存恢复成功,失败也有提示,并告诉你原因。
成功
比如百度使用了unload导致缓存失败 :)
结语:
回退前进缓存对提高性能,及用户体验很有帮助。大家要写正确的代码来使自己的页面尽量被缓存,这样你们的网站才能大大获益。
*请认真填写需求信息,我们会在24小时内与您取得联系。