Browserify with jQuery >= 2 produces "jQuery requires a window with a document"
browserify, commonjs, javascript, jquery
Solution
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.
Problem
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?