在 MutationObserver 中使用 document.write 会导致浏览器卡住并且 document.readyState 总是“正在加载”

问题描述 投票:0回答:0

免责声明:我知道为什么我应该避免使用 document.writedocument.write 清除页面

假设我需要在 DOM 加载时 (document.readyState = 'loading') 注入一个

synchronous
(阻塞)脚本,但就在另一个特定的现有同步脚本之前。

如果我可以访问 HTML 代码,我可以这样写:

<html>
  <head>
    <title>It's okay</title>
    <script>
      document.write(
        '<script src="https://www.googletagmanager.com/gtm.js?id=GTM-WZNT8QT" onload="console.log(1)"><'+'/script>'
      );
    </script>
    <script src="https://code.jquery.com/jquery-3.6.3.min.js" onload="console.log(2)"></script>
  </head>
  <body>
    <script>console.log('DOM is parsed')</script>
  </body>
</html>

它正确地加载了两个 JS 文件,并输出

1
,
2
,
DOM is parsed
到控制台。

现在,如果我尝试使用

MutationObserver
来做到这一点(即检测何时插入新脚本节点,但在实际调用脚本之前),

<html>
  <head>
    <title>Why not loading?</title>
    <script>
      // Say, this JS is invoked by the extension before even parsing HTML
      new MutationObserver((mutationList) => {
        for (const mutation of mutationList) {
          for (const node of mutation.addedNodes) {
            if (node.tagName !== 'SCRIPT' || !node.src.includes('jquery')) {
              continue;
            }
            document.write(
              '<script src="https://www.googletagmanager.com/gtm.js?id=GTM-WZNT8QT" onload="console.log(1)"><'+'/script>'
            );
          }
        }
      }).observe(document, { childList: true, subtree: true });
    </script>
    <script src="https://code.jquery.com/jquery-3.6.3.min.js" onload="console.log(2)"></script>
  </head>
  <body>
    <script>console.log('Now DOM is parsed!')</script>
  </body>
</html>

...它不仅使浏览器“始终加载”某些内容,而且永远不会将

2
Now DOM is parsed!
打印到控制台。检查实际的 HTML 代码后,头部只有“googletagmanager”脚本。 JavaScript 线程未被阻塞。实际上
document.readyState
从那一刻起总是停留
'loading'
,有效地卡住和破碎。

问题:

  1. 为什么会这样?你怎么解释呢?我的期望是这两个脚本都会被调用。
  2. 有什么方法可以在执行特定脚本(已经存在于 HTML 代码中)之前加载一段 同步 代码? (无法访问编辑 HTML,但能够在 HTML 被解析之前注入 JS,比如浏览器扩展等)。

事实上,有了

MutationObserver
,我至少可以通过在突变处理程序中说
jquery
来阻止
node.setAttribute('src', 'text/prevented')
代码运行,所以在它之前或之后插入googletagmanager脚本并不重要。我试图理解为什么它不起作用。

javascript html dom mutation-observers document.write
© www.soinside.com 2019 - 2024. All rights reserved.