10

我正在使用 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 包装了所有依赖项,this因此是一个object,而不是window.

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

4

5 回答 5

20

TL;博士;

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

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

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


非 TL;DR;

对于任何想知道原因的人来说,处理这个问题的 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.exports如下;

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

        return factory( w );

...这样如果jQuery 是 'd 时的对象this 它将返回一个 jQuery 实例,否则它将像以前一样返回工厂函数;因此,当 2.1.0实际发布时,您将不得不再次删除该调用。windowrequire()(window)

于 2013-12-04T17:06:21.127 回答
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);
于 2014-01-15T10:05:42.227 回答
5

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

var $ = require('jquery')(jsdom.jsdom().defaultView);
于 2015-10-13T05:39:26.233 回答
4

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

但是,以下允许我获得在节点中工作的最新版本的 JQuery:

var $ = require('jquery')(require("jsdom").jsdom().parentWindow);
于 2014-09-17T00:43:52.313 回答
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());
于 2016-01-20T12:07:13.407 回答