Electron: jQuery 未全局设置,因为定义了“模块”

创建于 2014-05-06  ·  71评论  ·  资料来源: electron/electron

jQuery 包含以下内容:

if ( typeof module === "object" && typeof module.exports === "object" ) {
  // set jQuery in `module`
} else {
  // set jQuery in `window`
}

模块已定义,即使在浏览器端脚本中也是如此。 这会导致 jQuery 忽略window对象并使用module ,因此其他脚本不会在全局范围内找到$jQuery ..

我不确定这是 jQuery 还是 atom-shell 错误,但我想把它放在网上,所以其他人不会像我那样搜索。

最有用的评论

只需取消设置module

我想让我的网页在浏览器和电子中都能工作。
正如本线程中所解释的,当nodeIntegration: true时,electron 会暴露一个全局的module nodeIntegration: true ,然后 jQuery 会看到并做出相应的反应:

if ( typeof module === "object" && typeof module.exports === "object" ) {
    // bind to module
} else {
    // bind to window
}

通过在我的 html 文件中执行以下操作,我能够让 jQuery 绑定到window对象并使用nodeIntegration: true

<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.highcharts.com/highcharts.js"></script>
<script>if (window.module) module = window.module;</script>

希望这可以帮助某人。

所有71条评论

这对于任何一个系统来说都不是真正的错误,使用 browserify 时会遇到同样的问题。 jQuery 看到它在 CommonJS 环境中运行,并希望如此使用。

然而,解决方案相对简单。 不是将 jQuery 作为脚本标签加载,而是通过 require 加载它:

window.$ = window.jQuery = require('/path/to/jquery');

我同意@ChiperSoft ,这是 CommonJS 环境中的预期行为,所以我将其标记为wontfix 。 感谢您分享您的发现。

@ChiperSoft ,我应该把 jquery.js 文件放在哪里才能让require('jquery')工作? 我试图将它放在与package.jsmain.js相同的级别,但运行时似乎没有发现它。

您可以使用require('jquery.js')注意最后的 .js,以加载相对于您的 HTML 文件的 jquery。

抱歉,我使用了window.$ = window.jQuery = require('/path/to/jquery');如上所述,但它不起作用,
Uncaught Error: Cannot find module 'scripts/jquery-1.10.2.min.js' module.js:339

我一直在使用它,而且效果很好! 这是我使用的,注意路径:

window.$ = window.jQuery = require('./scripts/jquery-2.1.1.min.js');

@frankhale哦,它适用于./ ,谢谢!

惊人的! 路径的事情也让我绊倒了。

如果您的应用程序不需要节点集成,请将"node-integration": false到您的 BrowserWindow 选项。 在这种情况下module.exports不可用,jQuery 工作正常。

@kabalage工作得很好,谢谢!

:+1:

走到了同样的问题。 通过 NPM 安装 jQuery 然后需要它并且它工作。

如果需要没有 require 的节点整数化和 jquery 怎么办...

我试图理解这一点,因为它似乎是我可以使用的东西。 但是我想知道你什么时候可以确定你可以安全地使用 $. 在此行之后立即记录 $ 将导致需要而不是 jquery,因为需要是异步的?

window.$ = window.jQuery = require('/path/to/jquery');
console.log($) // 记录“require”而不是“jQuery”

@dieroux尝试通过 npm 安装它:

npm install jquery

这对我有用,同时尝试相同。 那你就不用给路径了,直接说:

window.$ = window.jQuery = require('jquery');
console.log( [$, jQuery ]);

如果我们需要节点集成,而我们不能使用 require('something') 怎么办?
目前它通过执行“删除模块”来工作; 在加载有问题的东西之前。
这样做有什么影响?

我遇到了类似的问题,我第一次需要在 web 视图上的预加载脚本中正确加载 jquery。 但是,第二次从外部页面引用 jquery,通过以下方式分配它的行:

  try {
        module.exports = null;
        if (typeof require === 'function') {
          alert('window: ' + window);
          alert('jquery: ' + window.jQuery);
          alert('export: ' + module.exports);
          if ( !window.jQuery ) {
            alert('before load');
            window.jQuery = require('./node_modules/jquery/dist/jquery.js');
            alert('after load');
            window.$ = window.jQuery;
            alert('after assignment');
         }
          alert('jquery: ' + window.jQuery);
        }
    } catch(e) {
        alert('failed load.');
        console.log(e);
    }

在从 require 分配给 window.jQuery 时,在控制台中抛出无法读取 undefined 的属性 createElement,导致 jQuery 未加载。

控制台上的错误消息是:
访客页面记录了一条消息:类型错误:无法读取未定义行的属性“createElement”:40

关于如何在后续页面上成功加载 jquery 的任何其他想法?

谢谢。

这是我在运行电子快速入门并尝试包装本地应用程序时绊倒的第一件事 - 在 chrome 中工作的东西突然不在选举中。 将错误隐藏在失败的角度模块加载中当然无济于事,所以我假设脚本加载顺序存在问题,这就是我发现这个线程的方式。 也许关键字会帮助其他人。

@kabalage上面的解决方案工作得很好。

大家好,我只想添加一些有关此问题的信息,如果我将 jquery 库代码粘贴到电子控制台 $ 中,并且将 jQuery 作为函数添加到 window 对象中。 我可以运行jquery。

使用脚本标签引用 jQuery,同样的错误。 必须“节点集成”:BrowserWindow() 中的 false

大家好...我不知道为什么这个问题被关闭了,这里肯定还有一个问题,让我解释一下。 如果我通过 NPM 在本地安装 jQuery 并加载本地 html 文件,然后使用:

mainWindow.$ = require('jQuery');
mainWindow.jQuery = require('jQuery');

然后它按预期工作。 但是,如果我执行 mainWindow.loadUrl('http://external.site.com");

我收到了未定义 $ 和 jQuery 时提到的错误。 禁用节点集成确实不是一个可以接受的答案; 这就是我首先使用 Electron 的原因,我需要它。

我很想进入源头并自己解决这个问题,但我想在我去那里之前,我会看看是否有人有任何关于这方面的额外信息来为我指明正确的方向。 有没有人能够让它与节点集成一起工作,针对外部站点?

谢谢...和伟大的工作顺便说一句。 一切新鲜而美丽的事物,像这样,都将从几道皱纹开始。

亲切的问候

/W

我让它与节点集成一起工作。

  1. 用npm安装,所以在package.json中定义
  2. 使用 require 和模块名称<script>window.$ = window.jQuery = require('jquery');</script>
  3. 不要在 require 参数中使用路径。
  4. 不要安装低谷凉亭,它会让你在 require 参数中使用路径。
  5. 如果您使用引导程序,则需要先加载 jQuery。

以上所有仅由我的经验支持。

将工作

    <script>window.$ = window.jQuery = require('jquery');</script>
    <script src="path_to/bootstrap.js"></script>

将不会

    <script>window.$ = window.jQuery = require('./path/to/jquery.js');</script>
    // or
    <script src="path_to/jquery.js"></script>
    <script src="path_to/bootstrap.js"></script>

嗨 dilmdeep,感谢您的快速回复。 您的解决方案是否依赖于对外部站点的控制? 我正在尝试加载一个我没有源访问权限的站点。 不过你说的有关packages.json 的内容很有趣。 我确实通过 npm 安装了 jQuery(并使用了电子的记录重建),就像我说的,我可以将 jQuery 与本地 HTML 文件一起使用,但 jQuery 未在我的 package.json 中定义..... 哦,我测试了禁用节点集成,虽然这确实有效,但这不是我需要的。 谢谢。

我只是想更新这个以防其他人遇到同样的麻烦。 我解决这个问题的方式(在下载了 10GB 的 Electron 源之后)实际上是在文档中开始的。 我没有调用外部站点的 url,而是加载了一个本地 HTML 文件,并使用该 html 文件中的 webview 来加载外部站点。 它在启用节点集成的情况下完美加载。 只需查看 webview 的文档,它就非常简单。 还要感谢聊天室中的 Paul 帮助我开始使用源代码。 如果有人想知道他们使用 Atom(当然)来编码 Electron,使用 Windows 上的 WinDbg 进行调试,使用 Ninja 进行编译。 仅供参考,编译源代码非常简单且速度惊人,它首先使用他们的脚本和提供的文档进行编译。 再次,伟大的工作伙计们!

@WolfieWerewolf太棒了! 不得不说,如果考虑到安全性,这个例子有点误导。

@ Shufeng01干杯,伙计,我是从 .Net 来的,感觉就像一个完整的 n00b。 您是对的,安全性是一个问题,但是在 webview 本身上使用 disablewebsecurity 标志解决了大部分问题。 我认为总体而言,安全性是将 Web 引入桌面的最大挑战……但值得付出努力。 电子岩石。

@diimdeep谢谢,你的解决方案对我有用(不是

这对我们来说有点问题。 我们将 jquery 与我们的应用程序 js 捆绑在一起,然后将这个串联的 JS 用于 Web 和桌面版本的构建(我们一直在使用 NWJS)。 NPM 安装对我们来说可能是一个选择,但由于几个原因,它在我们的情况下并不理想。

有没有理论上的方法让它使用脚本标签工作?

@bgSosh ,为什么在此处阅读node-integration键)? 如果这样做,脚本标签应该可以正常工作。 如果您需要一些与节点相关的东西,您可以在preload脚本中执行此操作(它们始终具有节点集成)。

@etiktin你能详细说明如何在预加载中做到这一点吗? 我是电子的新手,havnt 设法获得了一个预加载脚本来执行(至少它似乎没有执行,console.log 不起作用,例如更改 window.myExposedIPC = require('ipc') 以后不可用等。

如果有人遇到同样的问题,我已经让它工作了: https :

@matthiasg很高兴你让它工作了。 我在你的例子中添加了一些评论。

当节点集成被禁用并且你想在你的预加载脚本中做一些节点的事情时,保持对你需要的任何节点全局的引用很重要。 您需要这样做,因为在下一个滴答声中,全局引用将被删除(这是禁用节点集成的实现方式),因此如果您没有持有引用,然后尝试在函数调用或计时器上要求某些内容,它会失败。

@etiktin谢谢。 当然,这是其中的一部分,但我缺少的是process.once('loaded', ... )的文档,一旦到位,我实际上可以公开我想要的 api。

嗨,大家好,

由于以上都不适合我(使用 w2ui 和 JQuery 与电子和独立的 HTML 页面,让 w2​​ui 也使用 jQuery),我觉得有必要在这里发布我的工作解决方案:

<html>
<head>
    <title>MyApp</title>
    <link rel="stylesheet" type="text/css" href="./lib/w2ui-1.4.3.css"/>
    <script type="text/javascript" src="./lib/require.js"></script>
    <script type="text/javascript" src="./lib/jquery-2.1.4.js" onload="$ = jQuery = module.exports;"></script>
    <script type="text/javascript" src="./lib/w2ui-1.4.3.js"></script>
</head>
<body>
<script type="text/javascript">
    // use global $ and w2ui here... 
    ...

我是 JS 的新手,正在进行技术研究,现在有点担心这个晦涩的模块加载内容。 这可能是一个愚蠢的问题,但为什么在加载 HTML 页面时电子加载 JS 模块与通常的浏览器如此不同?

@forman您是否禁用节点集成并使用预加载脚本进行节点交互? 请参阅我和@matthiasg 以上的评论。 如果你这样做,jquery 和其余的将像它们在浏览器中一样工作。

将工作

requirejs(['require', '../require.config'], function (requirejs, config) {
        //fixed jQuery isn't set globally
        requirejs(['jquery'],function(jquery){
            window.$ = window.jQuery =jquery;
        });
        // update global require config
        window.requirejs.config(config);
        // load app
        requirejs(['main'],function(main){
        });
    });

@forman谢谢!! 除了您的解决方案外,以上均无效。 (使用电子预建 0.35.5)
@etiktin这对我

认为我应该将我们的问题和解决方案添加到此线程以供将来参考。

我们正在 webview 中加载外部 url,需要执行我们自己的可以使用电子/节点的 Javascript。 在 webview 上启用 nodeintegration 不是一个选项,因为这会破坏外部 url 正在使用的 jQuery。

我们最终做的是向 webview 添加一个预加载脚本,我们将需要的模块放在全局范围内。 这使得稍后我们在执行 Javascript 时可以访问它们。

预加载.js:

global.ipcRenderer = require('electron').ipcRenderer;

然后我们可以像这样访问 ipcRenderer:

webview.executeJavaScript("ipcRenderer.sendToHost('hello');");

Uncaught Error: Cannot find module 'jquery'和这个线程没有任何帮助=/

只需取消设置module

我想让我的网页在浏览器和电子中都能工作。
正如本线程中所解释的,当nodeIntegration: true时,electron 会暴露一个全局的module nodeIntegration: true ,然后 jQuery 会看到并做出相应的反应:

if ( typeof module === "object" && typeof module.exports === "object" ) {
    // bind to module
} else {
    // bind to window
}

通过在我的 html 文件中执行以下操作,我能够让 jQuery 绑定到window对象并使用nodeIntegration: true

<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.highcharts.com/highcharts.js"></script>
<script>if (window.module) module = window.module;</script>

希望这可以帮助某人。

@tomkel这里是另一种解决方案:

<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>window.jQuery = window.$ = module.exports;</script>

就我而言,我需要能够将我的应用程序作为网站和电子应用程序启动。 这是我的解决方案:

<!-- Launched with Electron -->
<script>
    if ('require' in window) {
        window.$ = window.jQuery = require('jquery');
    }
</script>

<!-- From CDN, Bower, etc... -->
<script src="https://code.jquery.com/jquery-2.2.0.js"></script>

<!-- Others libraries depending on jQuery -->
<script src="..."></script>

@dkfiresky是的,这似乎也有效。 但是,我将 Highcharts 与 jQuery 结合使用。 Highcharts 做了类似的事情,如果它存在,将自己放在module 。 无论出于何种原因我无法得到

<script>window.Highcharts = module.exports;</script>

去工作。 我已经更新了我之前的评论以反映这一点。

@tomkel你的解决方案与module的时间隐藏对我来说非常有效。 我的问题是在从 nw.js 迁移到 ngDialog 期间,假设它在 CommonJS 环境中未能require('angular')并将自己注册为 angular 模块。

在 Electron 0.36.7 中,我发现我不能做一个简单的window.$ = require('jquery');因为它找不到模块。 渲染器似乎没有与主进程相同的模块解析路径

实际上这不起作用,因为 jQuery 将在没有document的主进程中运行。 而require('jquery')对我不起作用,因为我通过 HTTP 为页面提供服务,例如 #4243。 为了解决这个问题,我尝试通过以下方式将模块路径从主进程添加到渲染器进程:

require('electron').remote.process.mainModule.paths.forEach(function(path) {
    require('module').globalPaths.push(path);
});

之后我可以毫无问题地做require('jquery') 。 不确定这可能会产生什么其他影响

并且 require('jquery') 对我不起作用,因为我通过像 #4243 这样的 HTTP 为页面提供服务。

如果您允许远程内容访问 node.js,您的应用程序非常不安全,您需要在运行远程内容时禁用节点集成并使用预加载脚本

即使“远程内容”是本地主机? 我正在使用节点来构建和为我提供页面,而不是从本地文件中读取,仅此而已

扩展@dkfiresky ,您可能会在浏览器版本中获得Uncaught ReferenceError: module is not defined

如果是这样,试试这个:

<script src="./bower_components/jquery/dist/jquery.min.js"></script>
<script>window.jQuery = window.$ = typeof module === 'object' ? module.exports : jQuery</script> 

只有在禁用节点集成的情况下, @dspint module才会未定义,因此您可能应该仅在启用节点集成的情况下使用我的示例。

如果您使用的是window.open ,则可以使用窗口选项传递nodeIntegration=0

window.open('https://your.cool/url', 'title', 'nodeIntegration=0');

我正在做:

<script>
  var saveModule = module;
  delete module;
</script>
  <script src="jquery.js"></script>
  <script src="jquery-ui.js"></script>
<script>
  module = saveModule;
</script>

我和@gail 遇到了同样的问题。 我有一个运行 angular 项目的节点服务器。 他的代码为我修复了它。

require('electron').remote.process.mainModule.paths.forEach(function(path) {
  require('module').globalPaths.push(path);
});

它对我有用😄

<script>
    window['old_module'] = window['module'];
    delete window.module;
</script>

<script src="any_lib_like_jquery.js" />

<script>
    window['module'] = window['old_module'];
    delete window.old_module;
</script>

我遇到了这个问题,我已经尝试了所有这些线程。 但没有任何效果,我坚持开始
其中。
我正在使用电子启动器代表

@PauloGaldo基本上这个线程中的任何解决方案都应该有效。 请发布您的代码的相关摘录以及您遇到的所有错误消息。

@ChiperSoft你能告诉我我应该在哪里使用你的代码吗?

@tomkel非常好!
我终于让 Masonry 在 Electron 中工作了!

出于某种原因,我仍然无法让 jQuery 在浏览器和 Electron 应用程序中都能正常工作。
我的网络应用程序在浏览器中运行良好,而当我尝试通过电子应用程序加载相同的 url 时,它会抛出 -

image

网络应用程序 - https://github.com/zulip/zulip
电子应用程序 - https://github.com/zulip/zulip-electron

webapp 通过 npm 使用 jquery 1.12.1 版本。
我不能关闭节点集成,因为我在渲染器进程中需要它。
我很难解决这个问题。 有谁知道如何使它工作?
抄送@aaaaahaaaaa @maykefreitas @paulcbetts @tomkel @dkfiresky

@englishextra没有运气。 我试图将您的代码包含到我的应用程序的preload.js 中,但遇到了同样的错误。

@englishextra不,我的应用程序中不需要 jquery。 请参阅此处的更新代码。 我无法将您的代码包含在我的应用程序逻辑中,因为我仅将它用于加载指定的 url,请参阅

我用这个解决了这个问题

<script type="text/javascript" src="js/jquery.min.js" onload="window.$ = window.jQuery;"></script>

并设置

webPreferences: {
            nodeIntegration: false, 
        }

如果你像这样nodeIntegration: true, imorot jQuery

<script type="text/javascript" src="js/jquery.min.js" onload="window.$ = window.jQuery = module.exports;"></script>

参考
https://github.com/electron/electron/issues/345

我的意思是,这似乎是一个糟糕的问题,那么为什么不将它包含在实际的 Electron 中呢? 也许将主要的 JavaScript 库集成到 Electron 中?

很有可能,如果您在 Electron 应用程序中使用 jQuery,您会做一些非常错误或至少效率低下的事情。

<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};</script>

@drowlands在 Electron 中包含 3party 库似乎是个坏主意。 想象一下更新例程,例如,或选择一个版本。
@amhoho那是因为你需要require jQuery,或者在顶部函数修改它的初始化代码 - 只留下factory( global );

这里:

( function( global, factory ) {

    "use strict";

    if ( typeof module === "object" && typeof module.exports === "object" ) {

        // For CommonJS and CommonJS-like environments where a proper `window`
        // is present, execute the factory and get jQuery.
        // For environments that do not have a `window` with a `document`
        // (such as Node.js), expose a factory as module.exports.
        // This accentuates the need for the creation of a real `window`.
        // e.g. var jQuery = require("jquery")(window);
        // See ticket #14549 for more info.
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }

我的情况是我通过 fetch/Promise 或 xhr 加载库,所以我有这个例程来删除供应商库中的模块检查。
@RRorg奇怪你在说什么

标记

@kabalage我认为您上面帖子中的配置已过时。 现在看起来应该是这样的:

const window = new BrowserWindow({
  webPreferences: {
    nodeIntegration: false, 
  },
});

在官方文档上:
https://electronjs.org/docs/faq#i -can-not-use-jqueryrequirejsmeteorangularjs-in-electron
``