<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>缓存 &#8211; 科技改变生活-雨落星辰</title>
	<atom:link href="https://p1e.cn/html/tag/%E7%BC%93%E5%AD%98/feed" rel="self" type="application/rss+xml" />
	<link>https://p1e.cn</link>
	<description>所有的伟大,都源于一个勇敢的开始</description>
	<lastBuildDate>Wed, 12 Sep 2018 05:10:18 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.2</generator>
	<item>
		<title>两种浏览器缓存机制的了解</title>
		<link>https://p1e.cn/html/427.html</link>
					<comments>https://p1e.cn/html/427.html#respond</comments>
		
		<dc:creator><![CDATA[Naoki]]></dc:creator>
		<pubDate>Wed, 12 Sep 2018 05:10:18 +0000</pubDate>
				<category><![CDATA[运维笔记]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[缓存]]></category>
		<guid isPermaLink="false">https://www.815494.com/?p=427</guid>

					<description><![CDATA[浏览器缓存 浏览器缓存是指浏览器端用于在本地保存数据并进行快速读取的以避免重复资源请求的传输机制的统称。 打开Chrome浏览器，进入开发者工具，在Application那，你会发现有 HTTP 文件缓存、LocalStroage、SessionStorage、indexDB、Web SQL、Cookie、CacheStorage和Application Cache 。 这里只介绍 HTTP 文件缓存 和 Application Cache HTTP 文件缓存 HTTP 文件缓存是基于 HTTP 协议的浏览器文件级]]></description>
										<content:encoded><![CDATA[<h2 id="directory0300073947773903841">浏览器缓存</h2>
<p>浏览器缓存是指浏览器端用于在本地保存数据并进行快速读取的以避免重复资源请求的传输机制的统称。</p>
<p>打开Chrome浏览器，进入开发者工具，在Application那，你会发现有 HTTP 文件缓存、LocalStroage、SessionStorage、indexDB、Web SQL、Cookie、CacheStorage和Application Cache 。</p>
<p>这里只介绍 HTTP 文件缓存 和 Application Cache</p>
<h2 id="directory0300073947773903842">HTTP 文件缓存</h2>
<p>HTTP 文件缓存是基于 HTTP 协议的浏览器文件级缓存机制。这套机制决定了浏览器在文件重复请求时判断是否更新文件还是从本地读取文件。</p>
<p>流程图如下：</p>
<p><img fetchpriority="high" decoding="async" class="alignnone size-large wp-image-431" src="https://i.p1e.cn/2018/09/3982592708-1-1024x780.png" alt="" width="1024" height="780" /></p>
<p>流程图步骤说明：</p>
<ol>
<li>浏览器会先查询 <code>Cache-Control</code> 来判断内容是否过期，未过期则直接读取缓存文件，不发送 HTTP 请求，否则进入步骤2</li>
<li>浏览器判断上次文件的响应头是否有 <code>Etag</code>，有则连同 <code>If-None-Match</code> 一起发送请求，由服务器判断 <code>Etag</code> ，如未修改则返回304，修改则返回200，否则进入步骤3</li>
<li>浏览器判断上次文件的响应头是否有 <code>Last-Modified</code>，有则连同 <code>If-Modified-Since</code> 一起发送请求，由服务器判断 <code>Last-Modified</code> ，失效则返回200，未失效则返回304</li>
<li><code>Etag</code> 和 <code>Last-Modified</code> 都没有，则直接200</li>
</ol>
<p>补充说明：<code>Cache-Control</code> 跟 <code>Expires</code> 是类似的，但前者指的是相对过期时间，后者指的是绝对过期时间，如果两者同时设置，则只有 <code>Cache-Control</code> 生效</p>
<p>缓存时长计算公式：缓存时长 ＝ 响应时间 ＋ 缓存寿命 － 当前时间</p>
<p>响应时间指浏览器接收到服务端的响应的时间</p>
<p>如需了解更多，可以查看我另外一篇博文：<a href="https://www.linpx.com/p/web-cache-optimization.html" target="_blank" rel="noopener noreferrer">Here</a></p>
<h2 id="directory0300073947773903843">cacheStorage</h2>
<p>如果对 PWA 有所了解的话同学应该知道 PWA 的离线能力就是由 cacheStorage 提供，所以这部分也是成为重点部分。</p>
<p>在讲解 cacheStorage 先介绍一下 Application Cache 。</p>
<p>Application Cache 是一种允许浏览器通过 manifest 配置文件在本地有选择性地存储静态资源的文件级缓存机制。页面第二次以后打开，资源将会根据 manifest 配置描述有选择地读取本地 Application Cache 里面的文件。优势主要有：1、离线访问；2、加载速度快；3、服务器负载小。但缺点也很明显，包括：1、开始被标准弃用；不兼容主流(移动)浏览器；3、容量仅有5MB；4、资源失效时，更新也跟着失效；5、manifest要同源等等</p>
<p>这里再提一下 RAIL ，一个以用户为中心的性能模型，看到这里，你就知道了 Application Cache 其实并不怎么符合 RAIL</p>
<p>终于可以讲 cacheStorage 了</p>
<p>Google 强势推 PWA 以及其支持的技术，其中就有 ServiceWorker。cacheStorage 就是在 ServiceWorker 规范中定义的，用于保存每个 ServiceWorker 声明的 Cache 对象。</p>
<p>cacheStorage 在 Chrome 浏览器端里全局内置了 caches 对象，通过五个核心 API 方法直接对 Cache 对象进行操作，如下：</p>
<ul>
<li>caches.match() : 匹配key中含有该字符串的 Cache 对象，有返回一个 Promise 对象</li>
<li>caches.has() : 检查是否包含 Cache 对象，是则返回一个 Promise 对象</li>
<li>caches.open() : 打开或新建一个 Cache 对象并返回一个 Promise 对象</li>
<li>caches.delete() : 成功找到和删除 Cache 对象并返回一个 Promise 对象，否则返回false</li>
<li>caches.keys() : 遍历所有 Cache 对象，当含有keys中字符串的任意一个时返回一个 Promise 对象</li>
</ul>
<p>要了解 cacheStorage 就得深入了解 ServiceWorker，ServiceWorker 与 WebWorker 一样是在浏览器后台作为一个独立的线程去运行JavaScript，并通过 message 与 postMessage 方法在页面之间通信。移动端的原生应用一般都有消息推送、离线使用、自动更新等能力。如果使用 ServiceWorker 也可以让 Web 应用具备类似的能力。</p>
<p>在使用 ServiceWorker 时，通常需要先注册 一个 ServiceWorker JavaScript脚本，然后在里面写入 caches 的缓存控制方法，下图为 ServiceWorker 运行的生命周期</p>
<p><img decoding="async" class="alignnone size-full wp-image-430" title="两种浏览器缓存机制的了解" src="https://i.p1e.cn/2018/09/2578044744.png" alt="两种浏览器缓存机制的了解" /></p>
<p>注册 ServiceWorker</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">if</span>(navigator.serviceWorker){
  navigator.serviceWorker.register(<span class="hljs-string">'./sw.js'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">registration</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'sw注册成功'</span>);
  }).catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'sw注册失败'</span>);
  });
}</code></pre>
<p>sw.js里的缓存列表</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">let</span> cacheList = [<span class="hljs-string">'index.js'</span>,<span class="hljs-string">'index.css'</span>];</code></pre>
<p>将缓存列表注册到 cacheStorage 里，使用caches管理</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">this</span>.addEventListener(<span class="hljs-string">'install'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>)</span>{
  event.waitUntil(
    caches.open(<span class="hljs-string">'indexCache'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cache</span>)</span>{
      <span class="hljs-keyword">return</span> caches.addAll(cacheList);
    })
  );
});</code></pre>
<p>监听 ServiceWorker 的 fetch 方法，如果有响应则使用响应，否则读取缓存</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">this</span>.addEventListener(<span class="hljs-string">'fetch'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>)</span>{
  event.respondWith(cacnes.match(event.request).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">response</span>)</span>{
    <span class="hljs-keyword">if</span>(response){
      <span class="hljs-keyword">return</span> response;
    }
    <span class="hljs-keyword">let</span> responseToCache = response.clone();
    caches.open(<span class="hljs-string">'indexCache'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cache</span>)</span>{
      cache.put(event.request, responseToCache);
    });
  }));
});</code></pre>
<h2 id="directory0300073947773903844">总结</h2>
<p>通过横向了解 HTTP 文件缓存机制 和 ServiceWorker的cacheStorage，我们可以知道，前者是一种基于客户端的缓存策略，比较固定，而后者则是一种基于页端缓存策略，极具自由和可定制。</p>
<div></div>]]></content:encoded>
					
					<wfw:commentRss>https://p1e.cn/html/427.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
