用Greasemonkey替换页面的jQuery版本

如何用greasemonkey替换页面的jquery版本?

我试图用更新版本的jquery测试网站,但我没有开发环境。

我知道你要问jQuery和Greasemonkey这样做,但让我摆脱一个完全不同的选择, Fiddler 。

如果您正在使用新版本的jQuery测试网站,并且您实际上想要测试任何重大更改等…您希望测试网站,而不是基于后续的JavaScript(greasemonkey)事实替换不是一个准确的模拟。

使用fiddler,您可以替换浏览器请求的jQuery文件(无需浏览器知道)。 这样你实际上是在完全测试它,你是直接在页面中删除新版本,没有页面上的JS技巧,可能根本不准确到达那里(处理程序已经连接,加载顺序等。 )

Eric Law (Fiddler的创建者)有一篇关于如何做到这一点的优秀博客文章:

用Fiddler交换JQuery

这篇文章的目的是为了更换完整版本的缩小版本(也很方便!) 更新版本进行调试,请务必注意两种用途……它们在节省一些调试/测试时间方面都非常有用。

使用源代码控制和书面发布清单构建开发环境将为您节省更多的麻烦(并且是大多数付费工作的要求)。
~~~

在现有页面(您无法控制)上替换jQuery版本的最佳方法是:

  1. 停止页面的本机jQuery加载。
  2. 创建一个节点,其中包含所需的jQuery版本,该节点使用jQuery的任何后续脚本之前加载。

不幸的是,Greasemonkey无法做到#1。 它只能加载篡改页面的本机jQuery - 这种方法可能会起作用,但会降低页面速度并使竞争条件面临风险。

所以,我推荐一个双工具解决方案:

  1. 确保您的Firefox具有Adblock附加组件 (这是一个非常好的附件,可以无线使用)和/或RequestPolicy附加组件 。

  2. 使用AdblockRequestPolicy临时阻止旧的jQuery。
    例如,对于StackOverflow,请阻止http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js 。 (请注意, RequestPolicy允许您将URL阻止限制为仅限于特定站点。)

  3. 然后使用Greasemonkey在页面开头加载所需版本的jQuery(无论Adblock还是RequestPolicy设置都可以执行)。

    例如,此脚本将Meta SO的jQuery升级到1.6.2,与第2步中的块一起使用:

     // ==UserScript== // @name _upgrade jQuery // @include http://meta.stackexchange.com/questions/* // @run-at document-start // ==/UserScript== /*--- Important! (1) We need another add-on, besides Greasemonkey, to disable the old, undesired script. (2) The DOM is not available yet (@run-at == document-start). (3) We cannot use a loop to check for the DOM because loading is halted while the loop runs. (4) setTimeout() and setInterval() are not fast enough due to minimum interval clamping. By the time they detect the DOM, scripts that we need to precede may have loaded. (5) Therefor, we use a "set Zero Timeout" function as explained by David Baron at http://dbaron.org/log/20100309-faster-timeouts . (6) By the time FF reports that the `document.head` is available, several head elements have loaded! (Is this a bug?) That means that if any dependent scripts are loaded before we can inject our jQuery version, then we must also reload those dependent scripts. */ ////// setZeroTimeout() implementation: BEGIN /*--- Only add setZeroTimeout to the window object, and hide everything else in a closure. */ ( function () { var timeouts = []; var messageName = "zero-timeout-message"; /*--- Like setTimeout, but only takes a function argument. There's no time argument (always zero) and no arguments. You have to use a closure. */ function setZeroTimeout(fn) { timeouts.push(fn); window.postMessage(messageName, "*"); } function handleMessage(event) { if (event.source == window && event.data == messageName) { event.stopPropagation(); if (timeouts.length > 0) { var fn = timeouts.shift(); fn(); } } } window.addEventListener ("message", handleMessage, true); // Add the one thing we want added to the window object. window.setZeroTimeout = setZeroTimeout; })(); ////// setZeroTimeout() implementation: END /*--- Now wait for the DOM and then add our version of jQuery, first thing. */ function SearchForDOM () { var targetNode; if (typeof document.head == "undefined") targetNode = document.querySelector ("head, body"); else targetNode = document.head; if (targetNode) { var scriptNode = document.createElement ("script"); scriptNode.src = 'http://ajax.googleapis.com/ajax/' + 'libs/jquery/1.6.2/jquery.min.js'; targetNode.appendChild (scriptNode); /*--- By the time FF reports that the head element is available, a key dependent script has loaded! So, we reload it here, so that it can run with jQuery available. */ var scriptNode = document.createElement ("script"); scriptNode.src = location.protocol + '\/\/' + location.host + '/content/js/stub.js?v=49f661361016'; targetNode.appendChild (scriptNode); } else setZeroTimeout (SearchForDOM); } SearchForDOM (); 

    注意:由于JS,GM和Firefox的限制,可能需要重新加载依赖于jQuery的脚本。 (目前这是Meta Stack Overflow的情况。)

什么对我的情况不起作用,似乎适合这个问题,不需要阻止。 在GreaseMonkey中:

 // ==UserScript== // @name alternative jquery // @namespace ben@host // @description intercept // @include https://somehost.com/* // @grant GM_getResourceText // @resource jquery_new jquery_new.js // @run-at document-start // @version 1 // ==/UserScript== var jquery_source = GM_getResourceText( 'jquery_new' ); console.log('jQuery Lenght =',jquery_source.length); window.addEventListener('beforescriptexecute', function(e){ if (e.target.src && e.target.src.search('/1.12.4/jquery.min.js') >= 0 ) { console.log('intercepted: '+e.target.src); e.preventDefault(); e.stopPropagation(); window.eval(jquery_source); } }); 

注意:缺点 – 在检索到原始脚本并准备好执行之后, beforescriptexecute触发,因此如果原始外部js文件无法加载,则此方法将不起作用。