jQuery isn't set globally because "module" is defined #254

Closed
luto opened this Issue May 6, 2014 · 66 comments

Projects

None yet
@luto
luto commented May 6, 2014

jQuery contains something along this lines:

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

module is defined, even in the browser-side scripts. This causes jQuery to ignore the window object and use module, so the other scripts won't find $ nor jQuery in global scope..

I am not sure if this is a jQuery or atom-shell bug, but I wanted to put this on the web, so others won't search as long as I did.

@ChiperSoft

This isn't really a bug for either system, you have the same problem when using browserify. jQuery sees that its running in a CommonJS environment and expects to be used as such.

The solution is relatively simple, however. Instead of loading jQuery as a script tag, load it via require:

window.$ = window.jQuery = require('/path/to/jquery');
@zcbenz zcbenz added the wontfix label May 7, 2014
@zcbenz
Contributor
zcbenz commented May 7, 2014

I agree with @ChiperSoft, this is expected behavior in CommonJS environment, so I marked this as wontfix. And thanks for sharing your finding.

@zcbenz zcbenz closed this May 7, 2014
@alexdong
alexdong commented Jun 7, 2014

@ChiperSoft, Where should I put the jquery.js file to get require('jquery') working? I've tried to put it at the same level as package.js and main.js but the runtime doesn't seem to pick it up.

@Tribex
Contributor
Tribex commented Jun 7, 2014

You can use require('jquery.js') note the .js at the end, to load jquery relative to your HTML file.

@kurtharriger kurtharriger added a commit to kurtharriger/gorilla-web that referenced this issue Aug 31, 2014
@kurtharriger kurtharriger require jQuery fix for atom-shell
Atom shell appears to blow up when jquery is added as script tag.
electron/electron#254

Use commonjs syntax to export to window
60f1216
@mpcode
mpcode commented Sep 28, 2014

Sorry, I used window.$ = window.jQuery = require('/path/to/jquery'); as mentioned but it doesn't work,
Uncaught Error: Cannot find module 'scripts/jquery-1.10.2.min.js' module.js:339

@frankhale
Contributor

I use that all the time and it works great! Here is what I use, be mindful about the path:

window.$ = window.jQuery = require('./scripts/jquery-2.1.1.min.js');
@mpcode
mpcode commented Sep 28, 2014

@frankhale oh, it worked with ./, thanks!

@frankhale
Contributor

Awesome! The path thing tripped me up as well.

@cobalamin cobalamin added a commit to cobalamin/dripdownode that referenced this issue Oct 5, 2014
@cobalamin cobalamin Add loading message to spinner overlay.
Stop depending on jQuery and Vex, because electron/electron#254
is just ridiculous when loading non-file resources (__dirname is not set properly and process.cwd() is not usable)
fbb0682
@kabalage

If your app does not need node-integration, add "node-integration": false to your BrowserWindow options. In this case module.exports is not available, jQuery works like expected.

@miguelmota

@kabalage worked wonderfully, thanks!

@vrunoa
vrunoa commented May 6, 2015

👍

@RamonGebben

Walked up to the same issue. Install jQuery via NPM then required it and it worked.

@skandasoft

what if node integeration and jquery without the require is needed...

@dleroux
dleroux commented May 21, 2015

I'm trying to make sense of this since it appears to be something I could use. However I wonder when can you be sure you can safely use $. Logging $ right after this line will result would be require and not jquery since require is asynchronus?

window.$ = window.jQuery = require('/path/to/jquery');
console.log($) // logs 'require' not 'jQuery'

@RamonGebben

@dieroux try installing it via npm:

npm install jquery

This worked for me while trying the same. Then you don't need to give a path, you just say:

window.$ = window.jQuery = require('jquery');
console.log( [$, jQuery ]);
@devartblake devartblake added a commit to devartblake/Project_Hathor that referenced this issue Jun 29, 2015
@devartblake devartblake Error fixes
Fixed an error with jQuery not running properly with Twitter bootstrap
and the Electron framework.
Reference: electron/electron#254
166ceb9
@techninja techninja referenced this issue in evil-mad/robopaint Jul 12, 2015
Closed

Switch from nw.js to Electron? #215

@vikbez
vikbez commented Jul 16, 2015

What if we need node-integration, and we can't use require('something') ?
Currently it works by doing "delete module;" before loading problematic-stuff.
What's the impact of doing this ?

@ahazelwood

I'm having similar issues where jquery can be loaded correctly the first time I need it in a preload script on a webview. However the second time jquery is referenced from an external page, the line to assign it via:

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

throws a Cannot read property createElement of undefined in the console at the assignment to window.jQuery from require, resulting in jQuery not getting loaded.

Error message on the console is:
Guest page logged a message: TypeError: Cannot read property 'createElement' of undefined line: 40

Any additional thoughts on how to successfully load jquery on subsequent pages?

Thanks.

@vai
vai commented Sep 15, 2015

This was the first thing I tripped over when running through the electron quickstart and tried to wrap a local app - something working in chrome suddenly doesn't in election. Having the error buried in failed angular module loads doesn't help of course, so I assumed there was an issue with script load order, which is how I found this thread. Perhaps the keywords will help others.

@kabalage 's solution above worked perfectly.

@neeln4j
neeln4j commented Sep 30, 2015

Hello all ,I just want add some info with this issue , If i paste the jquery library code in electron console $ and jQuery is added as a function in window object. i could able to run jquery.

@diimdeep
diimdeep commented Oct 8, 2015

Referenced jQuery with script tag, same error. Have to "node-integration": false in BrowserWindow()

@WolfieWerewolf

Hi guys... I'm not sure why this issue is closed, there is definitely still an issue here, let me explain. If I install jQuery locally via NPM and load a local html file then using:

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

then it works as expected. If, however, I do mainWindow.loadUrl('http://external.site.com");

I get the errors mentioned where $ and jQuery are not defined. Disabling node integration is really not an acceptable answer; it's the reason I'm using Electron in the first place, I need it.

I'd be keen to get into the source and troubleshoot this myself but thought I would see if anyone had any additional information on this to point me in the right direction before I go down there. Has anyone been able to get this to work with node integration, against external sites?

Thanks... and great work BTW. Everything new and beautiful, like this, is going to start with a few wrinkles.

Kind Regards

/W

@diimdeep

I made it work with node-integration.

  1. Install it with npm, so it is defined in package.json
  2. Use require with module name <script>window.$ = window.jQuery = require('jquery');</script>
  3. Don't use path in require parameter.
  4. Don't install trough bower, it will make you to use path in require parameter.
  5. If you use bootstrap you need to load jQuery first.

All of above supported only by my experience.

Will work

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

Will not

    <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>
@WolfieWerewolf

Hi dilmdeep, thanks for the quick response. Does your solution depend on having control over the external site? I'm trying to load a site that I don't have source access to. What you said about packages.json is interesting though. I did install jQuery through npm (and used the documented rebuild for electron) and, like I said, I can use jQuery with a local HTML file, but jQuery is not defined in my package.json..... Oh and I tested with disabling node-integration and while that does work, it's not what I need. Thanks.

@WolfieWerewolf

I just wanted to update this in case someone else gets into the same trouble. The way I worked around this (after downloading 10GB of Electron source) was actually in the documentation to begin with. Instead of calling the url of the external site I loaded a local HTML file and used a webview from that html file to load the external site. It loads perfectly with node-integration enabled. Just look in the docs for webview, it's pretty straight forward. Also my thanks to Paul in the chatroom for helping me get started with the source. If anyone's wondering they use Atom (of course) to code Electron, WinDbg on windows to debug and Ninja to compile. FYI compiling the sources was dead easy and surprisingly fast, it compiled first go using their scripts and the provided documentation. Again, great work guys!

@shufenghui

@WolfieWerewolf Bravo! have to say the example is bit misleading if security is considered.

@WolfieWerewolf

@Shufeng01 Cheers mate, I'm coming at this cold from .Net land so feeling like a complete n00b. You're right that security was an issue however using the disablewebsecurity flag on the webview itself resolved most of it. I think security, in general, is the biggest challenge for bringing the web to the desktop... but well worth the effort. Electron rocks.

@psulek
psulek commented Oct 20, 2015

@diimdeep thanks, you solution works for me (not what @WolfieWerewolf wants!)

@bgSosh
bgSosh commented Nov 3, 2015

This is a bit of a problem for us. We bundle jquery with our app js, and this concatenated JS is then used in build for both the web and desktop versions (we have been using NWJS). NPM install may be an option for us, but it's not ideal in our situation for a couple of reasons.

Is there no theoretical way of getting it to work using script tags?

@etiktin
Contributor
etiktin commented Nov 4, 2015

@bgSosh, why not disable node integration (read about the node-integration key here)? If you do that, script tags should work correctly. If you need some node related stuff you could do that in a preload script (they always have node integration).

@jyapayne jyapayne referenced this issue in jyapayne/Web2Executable Nov 12, 2015
Closed

Will you ever make a similar tool for Electron? #96

@matthiasg

@etiktin can you please elaborate how to do this in preload ? i am new to electron and havnt managed to get a preload script to execute (at least it appears not to execute, console.log not working, changing window.myExposedIPC = require('ipc') for example is not available later etc.

@matthiasg

i have got it working in case anybody has the same issue: #1753 (comment)

@etiktin
Contributor
etiktin commented Nov 17, 2015

@matthiasg glad you got it working. I added some comments to your example.

When node integration is disabled and you want to do some node stuff in your preload script, it's important to hold a reference to what ever node global you need. You need to do this, because on the next tick the global references are deleted (this is how disabling node integration is implemented), so if you didn't hold a reference and you then try to require something on a function call or a timer, it would fail.

@matthiasg

@etiktin thanks. Of course that was part of it, but what i was missing is the documentation for process.once('loaded', ... ) once that was in place i can actually expose the apis i wanted.

@etiktin etiktin added a commit to etiktin/electron that referenced this issue Nov 18, 2015
@etiktin etiktin Update browser-window.md
Changed the description of the preload key to make it clear you need to provide an absolute file path and not a file url.
Also mentioned that it's possible to reintroduce Node globals when node integration is off and referenced the example from process.md (related to electron#254 (comment)).
f581730
@forman
forman commented Dec 16, 2015

Hi guys,

Since none of the above worked for me (using w2ui and JQuery both with electron and independent HTML page, let also w2ui use jQuery), I felt the need to post my working solution here:

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

I'm a newbie to JS and performing a technology study and now a bit worried about this obscure module loading stuff. It may be a silly question but why does electron load JS modules so differently from usual browsers when loading an HTML page?

@etiktin
Contributor
etiktin commented Dec 17, 2015

@forman did you disable node integration and use a preload script for node interaction? See the comments above by me and @matthiasg. If you do that, jquery and the rest will work exactly like they do in the browser.

@benkaiser benkaiser referenced this issue in benkaiser/stretto Dec 20, 2015
Closed

Issues with Electron #63

@capricornlee

Will work

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){
        });
    });
@hugohil
hugohil commented Jan 2, 2016

@forman Thank you !! None of the above worked excepted your solution. (using electron-prebuilt 0.35.5)
@etiktin This worked for me without having to change anything on the mainProcess side

@adamlj
adamlj commented Jan 13, 2016

Thought I should add our problem and solution to this thread for future reference.

We're loading an external url in a webview and need to execute our own Javascript that can use electron/Node. Enabling nodeintegration on the webview isn't an option since this will break jQuery that is being used by the external url.

What we ended up doing was adding a preload script to the webview where we put the modules we need in the global scope. This makes them accessible later on when we execute our Javascript.

preload.js:

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

And then we can access the ipcRenderer like:

webview.executeJavaScript("ipcRenderer.sendToHost('hello');");
@xywz xywz referenced this issue Feb 3, 2016
Closed

is this a bug? #4340

@Sigmanor
Sigmanor commented Feb 7, 2016

Uncaught Error: Cannot find module 'jquery' and nothing helps from this thread =/

@tomkel
tomkel commented Feb 12, 2016

Just unset module.

I wanted to have my webpage work both in the browser and in electron.
As explained in this thread, electron exposes a global module when nodeIntegration: true, which jQuery then sees and reacts accordingly:

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

I was able to get jQuery to bind to the window object and use nodeIntegration: true by doing the following in my html file:

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

Hope this helps someone.

@dkfiresky

@tomkel here is another solution:

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

In my case, I need to be able to both launch my application as a website and a Electron application. Here is my solution:

<!-- 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>
@tomkel
tomkel commented Feb 12, 2016

@dkfiresky Yes, that seems to work as well. However I'm using Highcharts in conjunction with jQuery. Highcharts does a similar thing, placing itself on module if it exists. For whatever reason I was unable to get

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

to work. I've updated my previous comment to reflect that.

@palavrov

@tomkel your solution with the temporal hiding of module works very well for me. My problem was during migration from nw.js with ngDialog assuming that it is in CommonJS environment failing to require('angular') and to register itself as angular module.

@gnail
gnail commented Feb 21, 2016

In Electron 0.36.7 I find that I cannot do a simple window.$ = require('jquery'); as it'd fail to find the module. I have to do window.$ = require('electron').remote.require('jquery'); to do it in the main process. The renderer doesn't seem to have the same module resolution path as the main process

Actually that doesn't work because jQuery would be running in the main process which doesn't have document. And require('jquery') didn't work for me because I'm serving the page through HTTP like #4243. To fix this I've tried adding module paths from the main process to the renderer process by:

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

After that I can do require('jquery') with no problems. Not sure what other impact this may have though

@paulcbetts
Contributor

And require('jquery') didn't work for me because I'm serving the page through HTTP like #4243.

If you are allowing remote content to access node.js, your app is very very insecure, you need to disable node integration when running remote content and use a preload script

@gnail
gnail commented Feb 22, 2016

Even if the "remote content" is localhost? I'm using node to build and serve me the page instead of reading from a local file, that is all

@dspint
dspint commented Mar 1, 2016

Expanding on @dkfiresky, you might get an Uncaught ReferenceError: module is not defined in the browser version.

If so, try this:

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

@dspint module will be undefined only in case of node integration is disabled, so you probably should use my example only with node integration enabled.

@luismbo luismbo added a commit to luismbo/ceramic that referenced this issue Mar 4, 2016
@luismbo luismbo Add node-integration option, defaulting to nil
This avoids issues like <electron/electron#254>.
50afd72
@justindujardin

If you are using window.open, you can pass nodeIntegration=0 with your window options.

window.open('https://your.cool/url', 'title', 'nodeIntegration=0');
@dvlsg dvlsg referenced this issue in dvlsg/async-csp Apr 8, 2016
Closed

Provide a browser build #13

@RRorg
RRorg commented Apr 10, 2016

I'm doing:

<script>
  var saveModule = module;
  delete module;
</script>
  <script src="jquery.js"></script>
  <script src="jquery-ui.js"></script>
<script>
  module = saveModule;
</script>
@dfournier dfournier referenced this issue in OneDrive/onedrive-api-docs Apr 22, 2016
Closed

File picker modal doesn't work with Electron #350

@kareljan

I had the same problem as @gnail. I had a node server running a angular project. His code fixed it for me.

require('electron').remote.process.mainModule.paths.forEach(function(path) {
  require('module').globalPaths.push(path);
});
@maykefreitas
maykefreitas commented May 14, 2016 edited

It's working for me 😄

<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

I'm having this issue, i've already tried all of this thread. but nothing works, im stuck on the beggining
of all.
i'm using the electron-starter rep

@RRorg
RRorg commented May 27, 2016

@PauloGaldo basically any solution in this thread should be working. Please post the relevant excerpt of your code and all error messages you encounter.

@Senney Senney added a commit to Senney/yakyak that referenced this issue Jun 9, 2016
@Senney Senney + Sean Heintz fix jQuery global window namespace registration
loginWindow is spawned with nodeIntegration set to True. Since
loginWindow will always be reaching out to external servers, we
can set nodeIntegration to False to prevent the 'module' global
namespace variable from being set.

electron/electron#254
8057796
@avh4 avh4 referenced this issue in aepsil0n/electron-elm-hello Jun 13, 2016
Open

Update for Elm 0.17 #1

@Vishal1419

@ChiperSoft Can you please tell me where should I use your code?

@englishextra

@tomkel Very nice!
I finally got Masonry to work within Electron!

@seldenr seldenr added a commit to seldenr/bunnybots2016 that referenced this issue Jul 10, 2016
@seldenr seldenr Added jQuery import support for electron 29470a6
@pikdum pikdum pushed a commit to pikdum/nbb that referenced this issue Aug 31, 2016
pikdum implement electron/electron#254 (comment) to fix jQuery and node inte…
…gration conflict
ad511e1
@msrodri msrodri pushed a commit to manifoldjs/manifoldjs-mac that referenced this issue Sep 15, 2016
Marcelo Rodriguez - Added workaround for workaround issue to set jQuery globally in the…
… pages (electron/electron#254)

- Added support to set the values of the name member (or short_name if name is not present) in the title bar
- Added support for background_color member
23cc745
@stelcheck stelcheck referenced this issue in docstrap/docstrap Sep 28, 2016
Open

electron: jQuery not found #252

@akashnimare
akashnimare commented Oct 4, 2016 edited

For some reason I'm still not able to make jQuery work both in browser and in Electron app.
My web app works fine in browser whereas when I try to load the same url via electron app it throws -

image

Webapp - https://github.com/zulip/zulip
Electron app - https://github.com/zulip/zulip-electron

The webapp is using jquery 1.12.1 version via npm.
I can't use nodeintegration off because I need it in my renderer process.
I'm having hard time solving this . Does anyone know how to make it work?
cc @aaaaahaaaaa @maykefreitas @paulcbetts @tomkel @dkfiresky

@akashnimare

@englishextra no luck. I tried to include your code into my app's preload.js but getting same error.

@akashnimare

@englishextra No, I don't need jquery in my app. See the update code here. I can't include your code into my app logic since I'm using it only for loading the specified url see this.

@lmj0011
lmj0011 commented Oct 26, 2016

for those using the Aurelia framework:
aurelia/skeleton-navigation@6292e69

@Bronts
Bronts commented Oct 28, 2016 edited

I resolved this problem with this

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

and set

webPreferences: {
            nodeIntegration: false, 
        }

if you with nodeIntegration: true, imorot jQuery like this

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

reference to
#345

@drowlands
drowlands commented Nov 2, 2016 edited

I mean, it seems to be a bad problem, so why not include it in actual Electron? Maybe integrate major JavaScript libraries into Electron?

@RRorg
RRorg commented Nov 3, 2016

Chances are, if you are using jQuery in an Electron App, you are doing something very wrong or at least inefficient.

@amhoho
amhoho commented Jan 13, 2017 edited
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};</script>
@englishextra
englishextra commented Jan 13, 2017 edited

@drowlands Including 3party libs in Electron seems to be a bad idea. Imagine the update routine, for instance, or chosing a version.
@amhoho That's because you need to require jQuery, or modify its init code at the top function - leaving only factory( global );

Here:

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

I my case I load libs via fetch/Promise or xhr, so I have this routine to remove module checks in vendors' libs.
@RRorg weird what you're saying

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment