用Greasemonkey替换页面的jQuery版本

时间:2011-10-09 00:51:03

标签: jquery greasemonkey

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

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

4 个答案:

答案 0 :(得分:10)

使用源代码控制和书面发布清单构建开发环境将为您带来更多的悲痛(并且是大多数付费工作的必要条件)。
~~~

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

  1. 停止加载页面的本机jQuery。
  2. 创建一个<script>节点,其中包含您想要的jQuery版本,在任何后续使用jQuery的脚本之前加载
  3. 不幸的是,Greasemonkey不能做#1。它只能在加载之后篡改页面的本机jQuery - 这种方法可能会起作用,但这会降低页面速度并使竞争条件面临风险。

    所以,我建议一个双工具解决方案:

    1. 确保您的Firefox有the Adblock add-on(这是一个非常好的附加组件,可以使用irregardless)和/或the RequestPolicy add-on

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

    3. 然后使用Greasemonkey在页面开头加载所需版本的jQuery(它可以执行 Adblock RequestPolicy 设置)。< / p>

      例如,此脚本将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的情况。)

答案 1 :(得分:5)

我知道你要求jQuery和Greasemonkey这样做,但让我完全完全不同的选择,Fiddler

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

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

Eric Law(Fiddler的创建者)有一篇关于如何完全的博客文章:

  

Swapping out JQuery with Fiddler

这篇文章的目的是为了更换完整版本的缩小版本(也很方便!)用于调试的新版本,请务必注意两种用途......它们都是< em>非常可以节省一些调试/测试时间。

答案 2 :(得分:1)

不确定Greasemonkey,但使用Requestly重定向规则是一种简单的方法来修改(URL,图像,脚本)上的任何资源。

  1. 从图标打开请求的应用程序(或导航至http://app.requestly.in/rules
  2. 点击“新规则”
  3. 选择“重定向请求”
  4. 输入请求源(在您的情况下为“ URL”“等于”:[URL到jquery,例如:“ http://some-host.com/jquery1.4.js”]
  5. 输入目的地(在您的情况下,为所需的jquery版本CDN的URL,例如:“ http://any-host.com/jquery3.2.js”)
  6. 点击保存
  7. 完成!现在,您的浏览器对源URL的所有请求都将重定向到您定义的目标URL。

注意:

  • 如果您没有CDN,则可以使用Requestly Library将文件托管在Web上。然后在目标网址字段下选择“从库中选择”。
  • 使用“取消请求”规则来阻止现有请求,可以获得相同的结果。然后使用“插入脚本”规则将您的脚本版本插入网页。

PS:我在Requestly工作。

答案 3 :(得分:0)

对我的案例没有用的东西,似乎适合这个问题,不需要阻挡剂。在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文件无法加载,则此方法将无效。