【问题标题】:Can link rel=preload be made to work with fetch?可以使链接 rel=preload 与 fetch 一起使用吗?
【发布时间】:2019-03-09 04:37:54
【问题描述】:

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

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

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

MDN claims 可以通过将crossorigin 添加到链接标签来解决此问题。 AFAICT,这不是真的,没有组合或跨域属性实际上可以使它起作用。

使用开发人员控制台中的 copy-as-curl 命令,似乎没有链接标记和属性的组合会发出与 JS 中的 fetch/XHR 调用相同的请求。

我很想在这件事上犯错。

【问题讨论】:

    标签: fetch preload


    【解决方案1】:

    看起来这是 Safari 和 Chrome 之间的区别。 Safari 将警告发布到控制台,但 Chrome 没有,所以也许将 crossorigin 添加到链接元素确实可以解决问题,但 Safari 存在某种错误?

    【讨论】:

    • 你设法让它工作了吗?我看到 Chrome 发出 3 个请求,而不仅仅是预加载一个 - 这是我想要实现的。
    • 是的。目前我在homicides.news.baltimoresun.com 上只看到一个对我的 JSON 文件的请求。
    • 对于未来的网络探险者,标签是<link rel="preload" as="fetch" href="/baltimore-homicides-victims-1543614381.json" id="victims-url" crossorigin>,JS 只是一个XMLHttpRequest。
    • 这在 Chrome 中有效,但在 Safari 12.0.3 中仍然无效;我在 homicides.news.baltimoresun.com 上看到两个对预加载 JSON 资源的请求和控制台警告:“资源 homicides.news.baltimoresun.com/… 已使用链接预加载进行预加载,但在窗口加载事件后的几秒钟内未使用。请确保它未预加载什么都没有。”
    【解决方案2】:

    感谢this bug 中的讨论,我让fetch 在 Chromium 67 中与preload 一起工作:

    首先,在预加载链接中添加crossorigin属性:

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

    其次,在 fetch 请求中添加同源凭证:

    fetch(url, {credentials: 'same-origin'}).then(response => {
        console.log(response);
    });
    

    或者,您可以使用 XMLHttpRequest 而不是 fetch(使用 XHR,您无需向请求添加任何内容),但前提是您不打算使用 responseType = 'blob' - 它不会由于another bug而工作。

    【讨论】:

    【解决方案3】:

    这是在 Chrome 和 Safari 中都可以使用并支持 cookie 的预加载 fetch 的有效解决方案。

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

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

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

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

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

    我尝试了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>
    

    上述方法在 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>
    

    以上内容在 Chrome 中有效,但在 Safari 中无效。虽然 cookie 是通过 preload 请求发送的,但 Safari 无法匹配 fetch 和 preload 请求,可能是因为 cors 模式不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 2021-07-29
      • 1970-01-01
      • 2016-08-07
      • 2018-09-15
      相关资源
      最近更新 更多