使用 Web Workers

在一个浏览器进程中,JavaScript 代码的执行是单线程的,同一时刻内只能有一段代码在执行,所以我们必须对资源进行分类,立即必需的资源应该没有任何阻塞的执行。在主题中,它不仅需要加载主题自身的内容(组件JS资源、埋点等立即必需的资源),它还需要加载用户安装的插件、第三方脚本(非立即必需的资源)。

当非立即必需的脚本过多时,立即必需和非立即必需的脚本仅仅只能在同一个单线程内排队执行,这时会有一些非立即必需的脚本执行在立即必需脚本之前,这样会导致展示页面所必需的资源加载时间变长,页面性能以及用户体验变差,总阻塞时间(详情参考:TBT)指标数值变大。

为了提供良好的用户体验、改进 TBT 指标,需要减少 JavaScript 执行时间和第三方代码的影响以及最小化主要线程工作。因此,我们引入了 Web Worker 来另外提供了一个线程开加载非立即必需的资源。

下面是加载脚本的工作流图示。

worker

  1. 首先,用户已经安装 App 或者自主引入第三方脚本到页面内
  2. 然后,在 seahorse 项目中会在页面中加入判断脚本是否需要放入 Web Worker 中执行的逻辑脚本
  3. 在页面中,找到符合以下条件的脚本:
  • 带有 scope="worker" 属性的脚本标签
  • 带有 src 且链接与在 Web Vitals Defender 插件中已安装加速的脚本的链接一致
4. 为符合条件的脚本准备 Worker 环境,新建 Worker 5. 将符合条件的脚本放入 Worker 中运行

脚本放入 Web Worker 中运行

跳转到“脚本放入 Web Worker 中运行”

符合以下三种形式之一的脚本会默认放入 Web Worker 中执行。

<!-- 第一种形式:带有 scope="worker" 属性,没有 type -->
<script scope="worker">
  // ...
</script>

<!-- 第二种形式:带有 scope="worker" 和 type="application/javascript" 属性 -->
<script scope="worker" type="application/javascript">
  // ...
</script>

<!-- 第三种形式:带有 scope="worker" 和 type="text/javascript" 属性 -->
<script scope="worker" type="text/javascript">
  // ....
</script>

当前第三方脚本需要在 Web Vitals Defender 插件中安装需要加速的脚本。

  • 在 worker 环境中是通过 postMessage 来与主线程通信的,所以在该环境里 JS 脚本是不能与主窗口进行通信。
  • 在 worker 环境中不支持一些较新的API,例如:insertAdjacentHTML。参考已支持的 DOM API文档。
  • 每个 spz-script 相当于一个隔离环境,他们之间不能互相通信。
本页目录