link rel=preload 可以和 fetch 一起使用吗?
Can link rel=preload be made to work with fetch?
我有一个很大的 JSON blob,我想用我的网页预加载。为此,我已将 <link rel="preload" as="fetch" href="/blob.json">
添加到我的页面。我也有一个 JS 请求来获取相同的 blob。
这不起作用,控制台报告:
[Warning] The resource blob.json was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it wasn't preloaded for nothing.
MDN claims 这可以通过将 crossorigin
添加到 link 标签来解决。 AFAICT,这是不正确的,没有任何组合或跨域属性实际上可以使它起作用。
使用开发人员控制台中的 copy-as-curl 命令,似乎没有 link 标记加属性的组合会发出与 JS 中的 fetch/XHR 调用相同的请求.
我很乐意在这一点上是错误的。
看起来这是 Safari 和 Chrome 之间的区别。 Safari 将警告发布到控制台,但 Chrome 没有,所以也许将 crossorigin
添加到 link 元素确实解决了问题,但 Safari 有某种错误?
感谢 this bug 中的讨论,我 fetch
可以在 Chromium 67 中使用 preload
:
首先,给preload添加crossorigin属性link:
<link rel="preload" as="fetch" href="/blob.json" crossorigin="anonymous">
其次,将同源凭据添加到获取请求中:
fetch(url, {credentials: 'same-origin'}).then(response => {
console.log(response);
});
或者,您可以使用 XMLHttpRequest
而不是 fetch
(对于 XHR,您不需要向请求添加任何内容),但前提是您不打算使用 responseType = 'blob'
- 由于 another bug.
它不会工作
这是预加载提取的工作解决方案,它在 Chrome 和 Safari 中都有效,并且支持 cookie。
不幸的是,它只适用于相同的域请求。
首先,不要为预加载标签指定crossorigin
属性,这将确保Safari以no-cors
模式发送请求并包含cookie
<link rel="preload" as="fetch" href="/data.json">
其次,提取 api 请求也应在 no-cors
模式下完成并包含凭据(cookie)。
注意这个请求不能有任何自定义的header(比如Accept
、Content-Type
等),否则浏览器将无法匹配这个请求和预加载的请求。
fetch('/data.json', {
method: 'GET',
credentials: 'include',
mode: 'no-cors',
})
我尝试了 crossorigin
属性值和获取 API 配置的其他组合,但其中 none 在 Safari 中对我有用(仅在 Chrome 中)。
这是我尝试过的:
<link rel="preload" as="fetch" href="/data.json" crossorigin="anonymous">
<script>
fetch('/data.json', {
method: 'GET',
credentials: 'same-origin',
mode: 'cors',
})
</script>
以上在 Chrome 中有效,但在 Safari 中无效,因为 cookie 不是通过 Safari 中的预加载请求发送的。
<link rel="preload" as="fetch" href="/data.json" crossorigin="use-credentials">
<script>
fetch('/data.json', {
method: 'GET',
credentials: 'include',
mode: 'cors',
})
</script>
以上内容在 Chrome 中有效,但在 Safari 中无效。虽然 cookie 是通过预加载请求发送的,但可能是因为 cors 模式不同,Safari 无法将 fetch 与预加载请求匹配。
我有一个很大的 JSON blob,我想用我的网页预加载。为此,我已将 <link rel="preload" as="fetch" href="/blob.json">
添加到我的页面。我也有一个 JS 请求来获取相同的 blob。
这不起作用,控制台报告:
[Warning] The resource blob.json was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it wasn't preloaded for nothing.
MDN claims 这可以通过将 crossorigin
添加到 link 标签来解决。 AFAICT,这是不正确的,没有任何组合或跨域属性实际上可以使它起作用。
使用开发人员控制台中的 copy-as-curl 命令,似乎没有 link 标记加属性的组合会发出与 JS 中的 fetch/XHR 调用相同的请求.
我很乐意在这一点上是错误的。
看起来这是 Safari 和 Chrome 之间的区别。 Safari 将警告发布到控制台,但 Chrome 没有,所以也许将 crossorigin
添加到 link 元素确实解决了问题,但 Safari 有某种错误?
感谢 this bug 中的讨论,我 fetch
可以在 Chromium 67 中使用 preload
:
首先,给preload添加crossorigin属性link:
<link rel="preload" as="fetch" href="/blob.json" crossorigin="anonymous">
其次,将同源凭据添加到获取请求中:
fetch(url, {credentials: 'same-origin'}).then(response => {
console.log(response);
});
或者,您可以使用 XMLHttpRequest
而不是 fetch
(对于 XHR,您不需要向请求添加任何内容),但前提是您不打算使用 responseType = 'blob'
- 由于 another bug.
这是预加载提取的工作解决方案,它在 Chrome 和 Safari 中都有效,并且支持 cookie。
不幸的是,它只适用于相同的域请求。
首先,不要为预加载标签指定crossorigin
属性,这将确保Safari以no-cors
模式发送请求并包含cookie
<link rel="preload" as="fetch" href="/data.json">
其次,提取 api 请求也应在 no-cors
模式下完成并包含凭据(cookie)。
注意这个请求不能有任何自定义的header(比如Accept
、Content-Type
等),否则浏览器将无法匹配这个请求和预加载的请求。
fetch('/data.json', {
method: 'GET',
credentials: 'include',
mode: 'no-cors',
})
我尝试了 crossorigin
属性值和获取 API 配置的其他组合,但其中 none 在 Safari 中对我有用(仅在 Chrome 中)。
这是我尝试过的:
<link rel="preload" as="fetch" href="/data.json" crossorigin="anonymous">
<script>
fetch('/data.json', {
method: 'GET',
credentials: 'same-origin',
mode: 'cors',
})
</script>
以上在 Chrome 中有效,但在 Safari 中无效,因为 cookie 不是通过 Safari 中的预加载请求发送的。
<link rel="preload" as="fetch" href="/data.json" crossorigin="use-credentials">
<script>
fetch('/data.json', {
method: 'GET',
credentials: 'include',
mode: 'cors',
})
</script>
以上内容在 Chrome 中有效,但在 Safari 中无效。虽然 cookie 是通过预加载请求发送的,但可能是因为 cors 模式不同,Safari 无法将 fetch 与预加载请求匹配。