Browserify with jQuery> = 2产生" jQuery需要一个带文档的窗口"

时间:2013-12-04 16:39:48

标签: javascript jquery commonjs browserify

我正在使用browserify使用CommonJS样式的依赖项捆绑我的前端javascript。例如,我有:

$ = require('jquery/dist/jquery');  // v2.1.0-beta2                                                                                                                                                                       
_ = require('underscore');                                                                                                                                                                                 
Backbone = require('backbone');

但是,当browserify将我遇到的依赖项捆绑到以下控制台错误中时:

Error: jQuery requires a window with a document

查看jQuery代码,我发现它正在尝试将this用于全局window

(function( window, factory ) {
....
}(this, function( window ) {

由于browserify包装了所有依赖项,thisobject,而不是window

有趣的是jQuery> = 2应该与CommonJS兼容。但是,问题是browserify如何包装依赖项。有人解决了这个问题吗?

5 个答案:

答案 0 :(得分:20)

TL; DR;

在您的情况下,它应该像使用一样简单;

$ = require('jquery/dist/jquery')(window);  // v2.1.0-beta2  

可能很明显;但是你必须在你使用的每个模块中使用这种形式的声明(将window传递给require的结果),而不仅仅是一个/第一个等等。


非TL; DR;

对于任何想要了解 why 的人来说,jQuery中处理这个问题的有趣代码是;

(function( window, factory ) {

    if ( typeof module === "object" && typeof module.exports === "object" ) {
        // Expose a jQuery-making factory as module.exports in loaders that implement the Node
        // module pattern (including browserify).
        // This accentuates the need for a real window in the environment
        // e.g. var jQuery = require("jquery")(window);
        module.exports = function( w ) {
            w = w || window;
            if ( !w.document ) {
                throw new Error("jQuery requires a window with a document");
            }
            return factory( w );
        };
    } else {
        factory( window );
    }

// Pass this, window may not be defined yet
}(this, function( window ) {

    // All of jQuery gets defined here, and attached to the (locally named variable) "window".

}));

请注意顶部的注释明确指出browserify;在jQuery在CommonJs-land中的情况下,而不是像我们所知的那样返回jQuery,它返回一个函数,当传递一个对象(应该是window)时,它返回jQuery。


为了进一步混淆此事,此设置代码在最新提交中再次更改,因此module.exportsdetermined like so;

module.exports = global.document ?
    factory( global ) :
    function( w ) {
        if ( !w.document ) {
            throw new Error( "jQuery requires a window with a document" );
        }

        return factory( w );

...如果this window对象,当jQuery为require()时,它将返回一个jQuery实例,如果不是它将像以前一样返回工厂功能;因此,当2.1.0 实际被释放时,您将不得不再次删除(window)来电。

答案 1 :(得分:6)

var $ = require('./node_modules/jquery');

//替换来源

var jsdom = require("./node_modules/jsdom");
var window = jsdom.jsdom().createWindow();
var $ = require('./node_modules/jquery/dist/jquery')(window);

答案 2 :(得分:5)

如果您使用的是jsdom的最新版本(6.x)和最新版本的jquery(2.1.4),您可以这样做:

var $ = require('jquery')(jsdom.jsdom().defaultView);

答案 3 :(得分:4)

使用CreateWindow()的上述解决方案对我不起作用。

但是,以下内容允许我在节点中使用最新版本的JQuery:

var $ = require('jquery')(require("jsdom").jsdom().parentWindow);

答案 4 :(得分:1)

我也能像Johnny Zhao那样包括它 - 但需要首先包括jsdom。

我安装了jquery和jsdom versjon: jquery@2.2.0 node_modules \ jquery jsdom@7.2.2 node_modules \ jsdom

然后跑了:

var jsdom = require("jsdom");
var $ = require('jquery')(jsdom.jsdom().defaultView);

$("<h1>test passes</h1>").appendTo("body");
console.log($("body").html());