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

北慕城南 提交于 2020-01-22 09:46:22

问题


I'm using browserify to bundle my front-end javascript using CommonJS-style dependencies. 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:

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.

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

Since browserify wraps all dependencies, this is an object, not the window.

What's interesting is jQuery >= 2 should be CommonJS compatible. However, the problem is how browserify wraps the dependencies. Has anyone solved this problem?


回答1:


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.


Non-TL;DR;

For anyone wanting to know why, the interesting code in jQuery which handles this is;

(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; 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.


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 = 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; so when 2.1.0 actually gets released, you'll have to remove the (window) call again.




回答2:


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);



回答3:


If you are using the latest version(6.x) of jsdom and the latest version of jquery(2.1.4), you can do this like:

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



回答4:


The solution above with CreateWindow() did not work for me.

However, the following allowed me to get the latest version of JQuery working in node:

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



回答5:


I was also able to include it like Johnny Zhao did - but needed to include jsdom first.

I installed jquery and 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());


来源:https://stackoverflow.com/questions/20380958/browserify-with-jquery-2-produces-jquery-requires-a-window-with-a-document

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!