干预 document.write()

您最近是否在开发者控制台中看到过如下警告: Chrome 并好奇这是什么?

(index):34 A Parser-blocking, cross-origin script,
https://paul.kinlan.me/ad-inject.js, is invoked via document.write().
This may be blocked by the browser if the device has poor network connectivity.

可组合性是 Web 的强大功能之一,让我们能够轻松 与第三方提供的服务集成,打造出色的新产品!一个 可组合的缺点在于,它意味着共同的责任 对用户体验的影响如果集成不够理想,用户体验 会受到负面影响

导致性能不佳的一个已知原因是在页面中使用 document.write(), 具体而言,就是那些注入脚本的用途。看起来像下面这样毫无危害, 可能会给用户带来切实的问题

document.write('<script src="https://example.com/ad-inject.js"></script>');

浏览器必须先通过解析 HTML 标记来构建 DOM 树,然后才能呈现网页。 每当解析器遇到脚本时,都必须停止并执行脚本,然后才能继续 来解析 HTML。如果脚本动态注入另一个脚本,则解析器将不得不等待 这样就会导致一次或多次网络往返 延迟网页首次呈现的时间

对于网速较慢(如 2G 网络)的用户,可动态地使用外部脚本 通过 document.write() 注入后,可能会导致主页面内容延迟 或导致网页无法载入或花费的时间过长,导致 用户直接放弃了根据 Chrome 中的插桩测试 包含通过 document.write() 插入的第三方脚本的网页 在 2G 网络下,加载速度通常比其他网页的两倍。

我们收集了 1% 的 Chrome 浏览器 28 天的现场试验数据 稳定版用户,仅限使用 2G 连接的用户使用。我们发现,占网页总加载次数的 7.6% 在 2G 网络中使用了至少一个跨站、解析器拦截脚本, 通过 document.write() 在顶级文档中插入。由于屏蔽操作 那么我们发现这些加载次数发生了以下改进:

  • 覆盖的页面加载次数增加了 10% 首次内容渲染 (向用户显示网页正在有效加载的视觉确认信息), 达到完全解析状态的网页加载时间增加 25%,重新加载次数减少 10% 这表明用户失望的程度有所降低。
  • 完成 平均时间缩短 1 秒以上, 首次内容渲染
  • 将解析网页所需的平均时间缩短了 38%, 缩短了将近 6 秒的时间,大大缩短了 展示对用户而言至关重要的信息

考虑到这些数据,Chrome 从版本 55 开始, 干预造成 检测到这种已知不良模式,并相应地更改 document.write() 的 (请参阅 Chrome 状态)。 具体而言,Chrome 不会执行通过<script> 在满足以下所有条件时为 document.write()

  1. 用户的网速较慢,特别是在使用 2G 网络时。(在 但将来网速较慢的其他用户可能也会遇到这一变化 例如慢速 3G 或慢速 Wi-Fi)。
  2. document.write() 位于顶级文档中。干预没有 适用于 iframe 中的 document.writing 脚本,因为它们不会阻止 主页面的呈现效果
  3. document.write() 中的脚本阻止了解析器。脚本与 “async” 或“defer” 属性仍会执行。
  4. 脚本未托管在同一网站上。也就是说,Chrome 会 不对具有匹配 eTLD+1 的脚本(例如,托管在 在 www.example.org 上插入了 js.example.org)。
  5. 该脚本尚不在浏览器 HTTP 缓存中。缓存中的脚本 不会导致网络延迟,并且仍会执行。
  6. 对页面的请求并非重新加载页面。如果遇到以下情况,Chrome 不会进行干预: 用户触发了重新加载并将正常执行该页面。

第三方代码段有时会使用 document.write() 加载脚本。 幸运的是,大多数第三方都提供 异步加载替代方案 允许加载第三方脚本,同时不阻止 网页内容

如何解决此问题?

这个简单的答案是不使用 document.write() 注入脚本,周三 维护一组支持异步加载器的已知服务 我们建议您持续检查。

如果您的提供商不在列表中,且支持异步脚本加载 请告知我们,我们会更新此页面,以便为所有用户提供帮助。

如果您的提供程序不支持异步加载脚本的功能 建议您与他们联系并 请告诉他们 将受到哪些影响

如果提供商为您提供包含 document.write() 的代码段,则 您或许可以向脚本元素添加 async 属性,或者 使用 DOM API(例如 document.appendChild())添加脚本元素 或 parentNode.insertBefore()

如何检测您的网站何时受到影响

决定是否强制执行此限制的标准有很多, 那么,您如何知道自己是否受到影响?

检测用户何时正在使用 2G

若要了解这项变更的潜在影响,您首先需要了解 会有多少人使用 2G 网络您可以检测用户当前的网络类型 Network Information API, ,然后会向分析指标或真实用户指标发送提醒, (RUM) 系统。

if(navigator.connection &&
    navigator.connection.type === 'cellular' &&
    navigator.connection.downlinkMax <= 0.115) {
    // Notify your service to indicate that you might be affected by this restriction.
}

在 Chrome 开发者工具中捕获警告

从 Chrome 53 开始,开发者工具会针对有问题的 document.write() 发出警告 语句。具体来说,如果 document.write() 请求满足条件 2 到 5 (在发送此警告时,Chrome 会忽略连接条件),该警告将会 如下所示:

文档写入警告。

在 Chrome DevTools 中看到警告固然很好,但是在 ?您可以检查在发送 进行干预。

检查脚本资源中的 HTTP 标头

通过document.write插入的脚本被屏蔽后,Chrome 会将 以下标头添加到请求的资源中:

Intervention: <https://shorturl/relevant/spec>;

当通过 document.write 插入的脚本被发现时,如果脚本在以下位置被阻止: Chrome 可能会发送:

Intervention: <https://shorturl/relevant/spec>; level="warning"

干预标头将作为脚本的 GET 请求的一部分发送 (如果发生实际干预,则异步执行)。

未来将会怎样?

我们最初的计划是,在检测到用户符合条件时, 目标。我们最初在 Chrome 53 的 Developer Console 中只显示了一条警告。 (测试版于 2016 年 7 月推出。我们预计将面向以下国家/地区的所有用户提供稳定版 2016 年 9 月。)

从以下时间开始,我们会进行干预,暂时阻止 2G 用户注入的脚本 Chrome 54(预计为稳定版本,可供以下国家/地区的所有用户使用) 2016 年 10 月中旬。请查看 Chrome 状态条目 了解更多最新动态。

随着时间的推移,我们希望当任何用户的网络连接速度较慢(例如 (慢速 3G 或 Wi-Fi)。按照这条 Chrome 状态条目操作。

希望了解更多信息?

如需了解详情,请参阅下面列出的其他资源: