使用 <link rel="preload"> (Chrome) 加载的资源的加载顺序行为不一致

Inconsistent load order behavior for the resources loaded with <link rel="preload"> (Chrome)

我正在尝试动态添加 <link rel="preload"> 标签以根据用户连接 navigator.connection.effectiveType 加载字体文件,例如如果有效类型是“4g”,则在任何其他资源之前在 head 标记中注入 <link as="font" type="font/woff2" rel="preload" crossorigin="anonymous" href="inter-var.woff2">,如果连接是 'slow-2g' / “2g” / “3g”,则不要注入 link.

我也在使用 preload 加载其他资源,但它们不像字体那么重要,因此它们是在字体文件之后注入的。

<head>
  // some other code
  <script id="connection-type-checker">
    (() => {
      const inter = document.createElement('link')
      const interItalic = document.createElement('link')
      const firaCode = document.createElement('link')

      inter.as = 'font'
      inter.type = 'font/woff2'
      inter.rel = 'preload'
      inter.crossOrigin = 'anonymous'
      inter.href = 'inter-var.woff2'

      interItalic.as = 'font'
      interItalic.type = 'font/woff2'
      interItalic.rel = 'preload'
      interItalic.crossOrigin = 'anonymous'
      interItalic.href = 'inter-var-italic.woff2'

      firaCode.as = 'font'
      firaCode.type = 'font/woff2'
      firaCode.rel = 'preload'
      firaCode.crossOrigin = 'anonymous'
      firaCode.href = 'fira-code.woff2'

      const insertAfter = (newNode, referenceNode) => referenceNode
        .parentNode.insertBefore(newNode, referenceNode.nextSibling)

      const target = document.getElementById('connection-type-checker')

      insertAfter(inter, target)
      insertAfter(interItalic, target)
      insertAfter(firaCode, target)
    })()
  </script>

  // **This is where <link>s get injected**

  // some other code...

  <link as="script" rel="preload" href="script.js" crossorigin="anonymous">
</head>

我面临的问题是,如果 link 元素是使用 [=55= 创建的,那么 Chrome 不会保持使用 link 预加载加载的资源的原始顺序](如果 link 元素在 head 标记中内联为 HTML,则一切正常。

截图:

我想了解为什么原始订单在 Chrome 中中断,是否可以修复?

Chrome 工程师在这里。据我所知,这里有一些不一致之处:

  1. 首先,根据您的图片,您可以看到 Firefox 实际上也在预加载之前获取 image.jpeg
  2. 其次,实际上我偶尔也会让 Safari 产生奇怪的顺序:

您在这里看到的是 Chrome(和其他一些浏览器)的后台 HTML 解析器在工作,它只是另一个轻量级解析器,可以快速浏览页面以寻找推测性(早期)获取的资源。通过在您创建的示例页面上调试 Chrome,事件发生的顺序大致为:

  1. 推测解析器启动了对 script.js
  2. 的请求
  3. 推测解析器启动了对 image.jpeg
  4. 的请求
  5. 普通解析器执行文档的挂起解析阻止脚本
  6. 按照添加的顺序获取三个预加载

所以在这种情况下,您会看到 speculative/background 解析器向前跳了一点,并在主解析器能够通过您的 script 标记之前开始获取内容。大多数浏览器都有这种解析器 here's an article about it,不幸的是它没有被任何标准指定,因为它不应该有任何可观察到的(对应用程序代码)影响。

但是,如果您因此而遇到性能问题,最好的办法是在 https://crbug.com 上提交 Chromium 错误,也许让我知道,我可以在合适的人面前找到它.

P.S。我注意到你提交了 https://github.com/w3c/preload/issues/146,如果可以的话,我可能会支持你提交一个 Chrome 错误。