Браузер с помощью jQuery >= 2 создает "jQuery требует окна с документом"

Я использую браузер, чтобы связать мой внешний интерфейс javascript с использованием зависимостей типа CommonJS. Например, у меня есть:

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

Тем не менее, при прошивке пакетов зависимостей я запускаю следующую консольную ошибку:

Error: jQuery requires a window with a document

Глядя на код jQuery, я вижу, что он пытается использовать this для глобального window.

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

Поскольку браузер оборачивает все зависимости, this является object, а не window.

Интересно, что jQuery >= 2 должен быть совместимым с CommonJS. Однако проблема заключается в том, как браузеру обертывает зависимости. Кто-нибудь решил эту проблему?

Ответ 1

TL; DR;

В вашем случае это должно быть так же просто, как использовать;

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

Это может быть очевидно; но вам придется использовать эту форму объявления (передать window в результат require) в каждом используемом вами модуле, а не только в одном/первом и т.д.


Non-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".

}));

Обратите внимание на комментарии вверху, которые явно адресуют браузеру; в ситуациях, когда jQuery находится в среде CommonJs, вместо возврата 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 );

... такое, что если this является объектом window, когда jQuery является require() 'd, он вернет экземпляр jQuery, или, если он не вернет функцию factory, как раньше; поэтому, когда версия 2.1.0 будет выпущена, вам придется снова удалить вызов (window).

Ответ 2

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

//заменить источники

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

Ответ 3

Если вы используете последнюю версию (6.x) jsdom и самую последнюю версию jquery (2.1.4), вы можете сделать это следующим образом:

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

Ответ 4

Решение выше с CreateWindow() не работает для меня.

Однако, это позволило мне получить последнюю версию JQuery, работающую в node:

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

Ответ 5

Я также смог включить его, как это сделал Джонни Чжао, но сначала нужно включить jsdom.

Я установил jquery и jsdom versjon: [email protected] node_modules\jquery [email protected] node_modules\jsdom

Затем выполнил:

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

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