可以使链接 rel=preload 与 fetch 一起使用吗?

Car*_*arl 12 fetch preload

我有一个很大的 JSON blob,我想预先加载我的网页。为此,我已添加<link rel="preload" as="fetch" href="/blob.json">到我的页面。我也有一个 JS 请求来获取相同的 blob。

这不起作用,控制台报告:

[警告] 资源 blob.json 是使用链接预加载预加载的,但在窗口加载事件的几秒钟内未使用。请确保它不是无故预加载的。

MDN 声称这可以通过添加crossorigin到链接标签来解决。AFAICT,这是不正确的,并且没有任何组合或跨域属性使其真正起作用。

使用来自开发者控制台的 copy-as-curl 命令,似乎没有链接标签和属性的组合,它们将发出与 JS 中的 fetch/XHR 调用相同的请求。

我很想在这件事上犯错。

Eug*_*lin 27

这是预加载 fetch 的工作解决方案,可在 Chrome 和 Safari 中运行并支持 cookie。

不幸的是,它仅适用于相同的域请求。

首先,不要指定crossoriginpreload 标签的属性,这将确保 Safari 将以模式发送请求no-cors并包含 cookie

<link rel="preload" as="fetch" href="/data.json">
Run Code Online (Sandbox Code Playgroud)

其次,fetch api 请求也应该在模式下完成no-cors并包含凭据(cookie)。请注意,此请求不能有任何自定义标头(例如AcceptContent-Type等),否则浏览器将无法将此请求与预加载的标头相匹配。

fetch('/data.json', {
    method: 'GET',
    credentials: 'include',
    mode: 'no-cors',
})
Run Code Online (Sandbox Code Playgroud)

我尝试过crossorigin属性值和获取 API 配置的其他组合,但它们在 Safari 中都不起作用(仅在 Chrome 中)。

这是我尝试过的:

<link rel="preload" as="fetch" href="/data.json" crossorigin="anonymous">

<script>
fetch('/data.json', {
    method: 'GET',
    credentials: 'same-origin',
    mode: 'cors',
})
</script>
Run Code Online (Sandbox Code Playgroud)

上面的代码在 Chrome 中有效,但在 Safari 中无效,因为 Safari 中的 cookie 不是通过预加载请求发送的。

<link rel="preload" as="fetch" href="/data.json" crossorigin="use-credentials">

<script>
fetch('/data.json', {
    method: 'GET',
    credentials: 'include',
    mode: 'cors',
})
</script>
Run Code Online (Sandbox Code Playgroud)

上面的代码在 Chrome 中有效,但在 Safari 中无效。虽然 cookie 是通过预加载请求发送的,但 Safari 无法将 fetch 与预加载请求匹配,可能是因为 cors 模式不同。