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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20380958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 18:22:16  来源:igfitidea点击:

Browserify with jQuery >= 2 produces "jQuery requires a window with a document"

javascriptjquerycommonjsbrowserify

提问by Brian Cray

I'm using browserify to bundle my front-end javascript using CommonJS-style dependencies. For example, I have:

我正在使用 browserify 使用 CommonJS 样式的依赖项来捆绑我的前端 javascript。例如,我有:

$ = 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 thisfor the global window.

查看 jQuery 代码,我看到它试图this用于全局window.

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

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

由于 browserify 包装了所有依赖项,因此thisobject,而不是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?

有趣的是 jQuery >= 2 应该与 CommonJS 兼容。但是,问题在于 browserify 如何包装依赖项。有没有人解决过这个问题?

回答by Matt

TL;DR;

TL; 博士;

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 windowto 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; in situations where jQuery is in CommonJs-land, instead of returning jQueryas we know it, it returns a function which, when passed an object (which should be window), returns jQuery.

请注意顶部的注释,其中明确指出了 browserify;在 jQuery 在 CommonJs 领域的情况下jQuery,它返回一个函数,而不是我们所知道的返回,当传递一个对象(应该是window)时,返回 jQuery。



To confuse the matter further, this setup code has changed again in the latest commit, so that module.exportsis 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 thisisthe windowobject 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 actuallygets released, you'll have to remove the (window)call again.

...这样,如果thiswindowjQuery 时的对象require(),它将返回一个 jQuery 实例,否则它将像以前一样返回工厂函数;因此,当 2.1.0实际发布时,您将不得不(window)再次删除该调用。

回答by user3197551

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

回答by Johnny Zhao

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:

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

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

回答by Alex Hawkins

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:

但是,以下内容使我能够在 node 中运行最新版本的 JQuery:

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

回答by Endre Moen

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: [email protected] node_modules\jquery [email protected] node_modules\jsdom

我安装了 jquery 和 jsdom 版本: [email protected] node_modules\jquery [email protected] 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());