如何将我自己的 jQuery 版本与浏览器化模块一起使用

How to use my own version of jQuery with browserified modules

(我应该先澄清一下:我的问题是关于 Javascript 中的闭包和客户端模块模式。这与如何使用 jQuery.noConflict() 无关。)

我有一些 Javascript 人们可以添加到他们的网站。我希望我自己的代码能够访问 $ 变量,该变量解析为 jQuery 的特定版本,该版本独立于页面加载的内容。如果我所有的代码都在一个文件中,在我定义的闭包中,这很容易。但是我正在努力寻找一种干净的方法来使用模块模式来执行此操作,其中我的代码位于单独的闭包中。

背景(即不是问题的显而易见的事情)

当我的所有代码都在一个文件中时,这很容易。我可以在最外层的闭包中创建一个 $ var 并使用 $.noConflict(...) 来确保外页保留其自己的 jQuery 版本。像这样:

// This is easy and works as you'd expect
(function() {

    var $; // The $ var in my local scope that the rest of my code can use.

    function loadMyVersionOfjQuery() {
        insertTheAppropriateScriptTagAndWaitForTheScriptToLoad(function() {
            // Set the $ in my local scope and restore the global jQuery.
            $ = jQuery.noConflict(true);
        }
    }

    loadMyVersionOfjQuery();

    ... etc. ...
})();

现在我正在使用 browserify 将我的代码分解成单独的文件,这不再那么容易了。最麻烦的是我的 jQuery 版本是异步加载的。所以在处理我的模块 requires() 时,我的 jQuery 版本还没有准备好。这使我无法在模块闭包的顶层简单地创建和分配 $ var。

我研究过的一些想法

  1. 如果我可以将模块的初始化推迟到 jQuery 为 运行 之后,那么我的每个模块都可以定义自己的 $ var。但这似乎不可能。看起来我的 requires(...) 调用被积极遍历,即使我试图将它们隐藏在函数回调中(browserify 似乎实际上解析 JS 以找到 require 语句)。
  2. 如果我可以定义一个动态代理对象,我可以用一个代理初始化我自己的 $ vars,该代理稍后会委托给我加载的 jQuery 版本。但是Javascript不支持动态代理模式。
  3. Browserify 实际上定义了一个闭包,当它们 "transpiled" 到单个文件时将我的所有模块包装起来。如果我能以某种方式给它一段代码来插入到这个闭包中(简单地 "var $;"),我就可以开始工作了。但是我还没有找到任何方法来做到这一点。
  4. 作为最后的手段,我想到我可以围绕 browserify 输出创建自己的闭包,并在那里定义我需要的作用域变量。通过处理输出文件或通过围绕 browserify 内容(类似于“(function(){var $;”+ bundle.js +“})();”)对几个简单文件进行 hacky 连接。但是这太hacky了。

有人有什么想法吗?您如何在多个文件中开发客户端 Javascript 模块,但仍将所有代码一起关闭?

可能我是唯一遇到这种情况的人(Browserify + 我想在我的所有模块中使用的异步加载库),但我会分享我的解决方法想出以防万一...

我最终定义了一个异步加载 jQuery 的模块,然后在准备就绪时通知侦听器。它基本上是对异步 'requires' 的非常简单的支持。我所有想要使用 jQuery 的模块都以这样的一小段样板代码结束:

var $; require('./jquery-provider').onLoad(function(jQuery) { $=jQuery; });

它并不完美,但很简单。它之所以有效,是因为我的库的入口点启动了我的 'jQuery provider' 并在调用我的所有其他模块之前等待准备好的回调。因此,尽管我的模块都被 Browserify 积极执行,因为它解决了所有依赖关系,但我的模块中的 none 函数得到 运行 直到我需要的库可用并已传递给它们。

(如果这个模式对其他人有用,我可以分享更多代码。)

在我的 app.js 我有这个

var $ = require('jquery')(window);  global.jQuery = require("jquery");

然后使用从 npm "plugin" 下载并导入 de 模块并执行,就像这样。

var plugin    = require('plugin');
plugin();

并且工作正常。