处理第三方的请求

大量的网站会使用不同源的文件,比如,你使用看谷歌字体,你需要从https://fonts.googleapis.com/导入样式和字体,对于一个文件来说,从不同源发起任何请求会被认为是跨域的请求,而且这些请求在Workbox中时是需要特殊处理的

在这个指南中,我们会探索一个跨域的请求是如何不同的,并且我们应该在Workbox中如何支持这些跨域的请求

跨域请求和不透明响应

浏览器中的一种安全机制是,当一段JavaScript请求来自其他来源的URL时,它就无法访问正文和响应的许多其他详细信息

当您收到这样的响应时,它被称为“不透明响应”。如果服务器返回CORS标头,则可以使用JavaScript读取某些请求,但是许多站点都不会这样做。

在service workers中,您可以向第三方发出请求并缓存响应。对于不透明的响应,响应的内容仍将被隐藏。您甚至无法查看响应的状态码。因此,Workbox对不透明响应的处理方式有所不同。您可以从此Stack Overflow Q&A中了解有关不透明响应的更多信息。

记得选择性加入跨域模式

如果您正在从支持CORS的第三方Web服务器上加载资源,但是出乎意料地返回了不透明的响应,则可能是取决于您的Web应用是如何发出这些跨源请求。

例如,以下HTML将触发一个会导致非透明响应的no-cors的请求,尽管example.com的服务器支持CORS

<link rel="stylesheet" href="https://example.com/path/to/style.css">
<img src="https://example.com/path/to/image.png">

为了显式触发cors请求并获取不透明的响应,您需要通过将crossorigin属性添加到HTML中来显式选择加入CORS模式

<link crossorigin="anonymous" rel="stylesheet" href="https://example.com/path/to/style.css">
<img crossorigin="anonymous" src="https://example.com/path/to/image.png">

Workbox有时候会缓存不透明的响应

通常,Workbox不会缓存不透明的响应。原因是很容易陷入不良状态。例如,开发人员使用CacheFirst策略设置了路由

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';

registerRoute(
  'https://cdn.google.com/example-script.min.js',
  new CacheFirst(),
);

该响应将缓存不透明的响应,并从那时起开始提供服务。问题在于,如果该请求由于任何原因而失败,Workbox将无法检测到该错误,并将继续处理无效的响应。用户将处于无法访问的状态。

但是,尝试为这些请求添加一些容错功能并不是一件坏事,因此Workbox将允许使用NetworkFirst和StaleWhileRevalidate策略来缓存不透明的响应。由于这些策略会定期更新缓存的响应,因此缓存它们会更安全,因为我们希望一个坏的请求的生命周期是短暂而且很少使用的。

import {registerRoute} from 'workbox-routing';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';

registerRoute(
  'https://cdn.google.com/example-script.min.js',
  new NetworkFirst(),
);

// OR

registerRoute(
  'https://cdn.google.com/example-script.min.js',
  new StaleWhileRevalidate(),
);
如果您使用其他缓存策略并且返回了不透明的响应,则Workbox会记录一条警告,告知您该响应尚未缓存。

cdn 引用 axios实现跨域 workbox cdn跨域_缓存

强制缓存不透明响应

如果确定要缓存不透明的响应,则可以使用插件配置该行为。本示例使用workbox-cacheable-response:

import {registerRoute} from 'workbox-routing';
import {NetworkFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';

registerRoute(
  'https://cdn.google.com/example-script.min.js',
  new CacheFirst({
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200]
      })
    ]
  }),
);

警告:这将缓存可能是错误的响应,因此在之后这个响应永远不会更新!