簡體   English   中英

Browserify with jQuery> = 2產生“jQuery需要一個帶文檔的窗口”

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

我正在使用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如何包裝依賴項。 有人解決了這個問題嗎?

TL; DR;

在你的情況下,它應該像使用一樣簡單;

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

...這樣如果this jQuery為require()window對象,它將返回一個jQuery實例,如果不是,它將像以前一樣返回工廠函數; 所以當2.1.0 實際上被釋放時,你將不得不再次刪除(window)調用。

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

//替換來源

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

使用CreateWindow()的上述解決方案對我不起作用。

但是,以下允許我在節點中使用最新版本的JQuery:

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

我也能像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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM