我试图在过去一个月左右的客户网站上找出问题,因为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有关。
答案 0 :(得分:2)
所以这在所有方面都是一个令人难以置信的混乱问题,并且在我修复之后仍然如此。
我们能够通过更新网站上使用的History.js lib来解决这个问题,因为我自己可以完全接受作为有效的故障排除步骤(因此我尝试了)。但是我对于History.js和gpt.js如何相互接口完全感到困惑。导致问题只发生在这种情况下:
使用Safari 使用旧版本的History.js 使用GPT(应该对History.js没有影响) 使用utm_source标记(对history.js或GPT不应有任何影响)
但我很高兴被一个固定的问题搞糊涂而不是流行的问题,所以我会把它留在“太难”的篮子里。
顺便说一句,我的主要问题是要做,而不是问题是否持续,所以这就是我如何对结论感到麻烦,以防它帮助其他人:
<head>
的顶部添加了一个脚本标记,它为beforeunload注册了一个事件处理程序,调用了调试器语句。这将使我有时间在页面刷新之前实际检查时间轴和分析器。接下来,我花了一些时间把头发拉出来,因为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]
以获取已安装计时器的函数的文本。