如何找到safari中不断页面刷新的原因?

时间:2015-01-07 01:53:43

标签: safari page-refresh google-dfp

我试图在过去一个月左右的客户网站上找出问题,因为iOS和OSX的最新更新。当Mac或iOS Safari的用户通过EDM中的链接定向到站点中的任何页面时,它们会被刷新的页面的常量循环中捕获。它似乎也在刷新之间泄漏了内存,因为Activity Monitor显示该站点的Safari Web Content进程在内存使用方面迅速增长(在我杀死之前的两分钟内达到4 GB)。

该问题只能在Safari浏览器上重现。 Mac上的Chrome似乎不受影响。 Safari for Windows显示刷新问题但似乎没有开始囤积内存,尽管WebKit2WebProcess.ee进程的CPU使用率持续相当高,直到窗口关闭。我尝试逐个删除添加到EDM链接的utm_ *参数,直到我可以确认问题是由它自己的utm_source引起的,然后发现我应该预料到,因为它显然是GA寻找的主要标记。更有意思的是删除GA没有解决问题 - 我注释了创建脚本标记的代码(为了它的价值,使用的脚本不是正常的www.google-analytics.com/ga.js而是来自stats.g.doubleclick.net/dc.js的DFP广告管理系统。

解决问题的原因是没有加载GPT - 评论以下代码:

var googletag = googletag || {};
    googletag.cmd = googletag.cmd || [];
    (function() {
        var gads = document.createElement("script");
        gads.async = true;
        gads.type = "text/javascript";
        var useSSL = "https:" == document.location.protocol;
        gads.src = (useSSL ? "https:" : "http:") + "//www.googletagservices.com/tag/js/gpt.js";
        var node =document.getElementsByTagName("script")[0];
        node.parentNode.insertBefore(gads, node);
    })();

所以我很确定GPT正在检测utm_source参数并尝试做某些事......在Safari上失败了...有些原因......不幸的是,GPT代码被混淆了,我不太可能找到我的问题只是阅读它,所以我希望有一些方法可以在Safari的开发者控制台刷新页面之前得到调用堆栈,我不知道,或者其他一些调试技术我没有想到。也许其他人甚至遇到过这个问题?

据我所知,关注这些参数的唯一脚本是谷歌分析,所以我也听到我正在走向花园小径。

编辑:我尝试取消注释GPT脚本标记,然后在页面上注释我们向其发送命令(使用googletag.cmd.push()),以防我们使用它导致问题(我们基本上只是然后定义然后在推送的cmd中发布8个插槽,然后启用广告服务)。注释此命令并未解决问题,它似乎与加载GPT有关。

1 个答案:

答案 0 :(得分:2)

所以这在所有方面都是一个令人难以置信的混乱问题,并且在我修复之后仍然如此。

我们能够通过更新网站上使用的History.js lib来解决这个问题,因为我自己可以完全接受作为有效的故障排除步骤(因此我尝试了)。但是我对于History.js和gpt.js如何相互接口完全感到困惑。导致问题只发生在这种情况下:

使用Safari 使用旧版本的History.js 使用GPT(应该对History.js没有影响) 使用utm_source标记(对history.js或GPT不应有任何影响)

但我很高兴被一个固定的问题搞糊涂而不是流行的问题,所以我会把它留在“太难”的篮子里。

顺便说一句,我的主要问题是要做,而不是问题是否持续,所以这就是我如何对结论感到麻烦,以防它帮助其他人:

  • 我在<head>的顶部添加了一个脚本标记,它为beforeunload注册了一个事件处理程序,调用了调试器语句。这将使我有时间在页面刷新之前实际检查时间轴和分析器。
  • 这向我展示了在beforeunload事件之前,一个popstate事件被调用(事后看来,当我看到popstate时,我谴责自己没有直接进入History.js)。这个事件安装了一个计时器,我注意到它立即被触发,然后每1000毫秒。这是在beforeunload事件之前在popstate事件中触发的最后一件事,所以我认为很有可能导致刷新。
  • 接下来,我花了一些时间把头发拉出来,因为safari没有在它的时间轴中暴露事件的调用堆栈。我知道如何在Chrome中实现这一点,但我无法在Chrome中解决问题。我不得不继续使用计时器ID。最终我像这样覆盖了setTimeout:

    var origST = window.setTimeout;
    window.timers = [];
    window.setTimeout = function(f,t) {
      window.timers[origST(f,t)] = window.setTimeout.caller ? window.setTimeout.caller : 'Global Scope';
    }
    
  • 并为setInterval做了同样的事情。然后我可以重新加载页面,获取计时器的ID,然后在控制台中检查timers[the id]以获取已安装计时器的函数的文本。

  • 接下来我需要搜索所有已加载的脚本文件以查找有问题的函数定义(这是一个混淆和丑化的脚本,而不是我可以轻易猜到的)我不确定这在Safari中是否真的可行,如果它是我无法弄清楚如何。幸运的是,这不依赖于重现问题所以我加载了Chrome并使用它的开发工具来搜索脚本文件。
  • 在History.js中查找功能,我们对其进行了更新,发现问题已解决。