简体   繁体   English

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

[英]Browserify with jQuery >= 2 produces “jQuery requires a window with a document”

I'm using browserify to bundle my front-end javascript using CommonJS-style dependencies. 我正在使用browserify使用CommonJS样式的依赖项来捆绑我的前端javascript。 For example, I have: 例如,我有:

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

However, when browserify bundles the dependencies I run into the following console error: 但是,当browserify捆绑我遇到的依赖项时,会出现以下控制台错误:

Error: jQuery requires a window with a document

Looking at the jQuery code, I see it's trying to use this for the global window . 看看jQuery代码,我看到它正在尝试将this用于全局window

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

Since browserify wraps all dependencies, this is an object , not the window . 由于browserify包装了所有依赖项, this是一个object ,而不是window

What's interesting is jQuery >= 2 should be CommonJS compatible. 有趣的是jQuery> = 2应该与CommonJS兼容。 However, the problem is how browserify wraps the dependencies. 但是,问题是browserify如何包装依赖项。 Has anyone solved this problem? 有人解决了这个问题吗?

TL;DR; TL; DR;

In your case, it should be as simple as using; 在你的情况下,它应该像使用一样简单;

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

It might be obvious; 这可能是显而易见的; but you'll have to use this form of declaration (pass window to the result of require ) in every module you use, not just one/ the first, etc. 但是你必须在你使用的每个模块中使用这种形式的声明(将window传递给require的结果),而不仅仅是一个/第一个等等。


Non-TL;DR; 非TL; DR;

For anyone wanting to know why , the interesting code in jQuery which handles this is; 对于任何想知道原因的人来说 ,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".

}));

Note the comments at the top which explicitly address browserify; 请注意顶部的注释明确指出browserify; in situations where jQuery is in CommonJs-land, instead of returning jQuery as we know it, it returns a function which, when passed an object (which should be window ), returns jQuery. 在jQuery位于CommonJs-land中的情况下,它不是像我们所知的那样返回jQuery ,而是返回一个函数,当传递一个对象(应该是window )时,返回jQuery。


To confuse the matter further, this setup code has changed again in the latest commit, so that module.exports is determined like so ; 为了进一步混淆这个问题,这个设置代码在最近的提交中再次发生了变化,因此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 );

... such that if this is the window object when jQuery is require() 'd, it will return a jQuery instance, or if not it'll return the factory function as before; ...这样如果this jQuery为require()window对象,它将返回一个jQuery实例,如果不是,它将像以前一样返回工厂函数; so when 2.1.0 actually gets released, you'll have to remove the (window) call again. 所以当2.1.0 实际上被释放时,你将不得不再次删除(window)调用。

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

//replace sources //替换来源

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

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

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

The solution above with CreateWindow() did not work for me. 使用CreateWindow()的上述解决方案对我不起作用。

However, the following allowed me to get the latest version of JQuery working in node: 但是,以下允许我在节点中使用最新版本的JQuery:

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

I was also able to include it like Johnny Zhao did - but needed to include jsdom first. 我也能像Johnny Zhao那样把它包括在内 - 但需要首先包括jsdom。

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

Then ran: 然后跑了:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM