1

In a Nutshell: I am implementing a single-page website using Electron and encountered the common issue of jQuery not being globally accessible. So I simplified the problem by using the quick start example in the following in order to figure it out, but I cannot make sense of it.

As you can see, I have simply added the following code to the end of my main.js file to check if the issue is resolved:

$(document).ready(function () {
    console.log("hi");
});

This is the complete code of my main.js file:

// main.js
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require("electron");
const path = require("path");

function createWindow() {
    // Create the browser window.
    const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
        preload: path.join(__dirname, "preload.js"),
        nodeIntegration: true,

        webSecurity: true,
    },
    });

    // and load the index.html of the app.
    mainWindow.loadFile("index.html");

    // Open the DevTools.
    // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
    createWindow();

    app.on("activate", function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
    });
});

// Quit when all windows are closed.
app.on("window-all-closed", function () {
    // On macOS it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== "darwin") app.quit();
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

$(document).ready(function () {
    console.log("hi");
});

I am loading the following HTML code into my BrowserWindow:

<!DOCTYPE html>
<html>
    <head>

    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->

    <!--This was added otherwise "window.jQuery = window.$ = require('jquery');" will not be executed-->
    <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' http://* 'unsafe-inline'; script-src 'self' http://* 'unsafe-inline' 'unsafe-eval'" />

    <title>Hello World!</title>
    </head>
    <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <script src="node_modules/jquery/dist/jquery.min.js"></script>
    <script>window.jQuery = window.$ = require('jquery');</script>
    <script src="./renderer.js"></script>

    </body>
</html>

Below script is attached to the BrowserWindow as a preload script as advised by the Electron documentation:

// Preload.js
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener("DOMContentLoaded", () => {
    const replaceText = (selector, text) => {
    const element = document.getElementById(selector);
    if (element) element.innerText = text;
    };

    for (const type of ["chrome", "node", "electron"]) {
    replaceText(`${type}-version`, process.versions[type]);
    }
});

Last but not least, this is the package.json configuration file of the quick start project:

{
    "name": "electron-quick-start",
    "version": "1.0.0",
    "description": "A minimal Electron application",
    "main": "main.js",
    "scripts": {
        "start": "electron ."
    },
    "repository": "https://github.com/electron/electron-quick-start",
    "keywords": [
        "Electron",
        "quick",
        "start",
        "tutorial",
        "demo"
    ],
    "author": "GitHub",
    "license": "CC0-1.0",
    "devDependencies": {
        "electron": "^9.0.2"
    },
    "dependencies": {
        "jquery": "^3.5.1"
    }
}

However, each time I run the app, I get the following error prompt:

pop up window

This error is also shown in my app's Powershell output (I have only redacted the full directory path):

App threw an error during load
ReferenceError: $ is not defined
  at Object.<anonymous> (...directory\0masterproject\main.js:48:1)
  at Module._compile (internal/modules/cjs/loader.js:967:30)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:1004:10)
  at Module.load (internal/modules/cjs/loader.js:815:32)
  at Module._load (internal/modules/cjs/loader.js:727:14)
  at Function.Module._load (electron/js2c/asar.js:738:28)
  at loadApplicationPackage (...directory\0masterproject\node_modules\electron\dist\resources\default_app.asar\main.js:109:16)    at Object.<anonymous> (...directory\0masterproject\node_modules\electron\dist\resources\default_app.asar\main.js:155:9)
  at Module._compile (internal/modules/cjs/loader.js:967:30)
  at Object.Module._extensions..js (internal/modules/cjs/loader.js:1004:10)
PS ...directory\0masterproject> npm start

However, when I close this window and check the BrowserWindow's console, I do not see any error, but no "hi" output either.

Before I ran into this issue, I had the problem that require () was not defined, which I have resolved by adding

<script src="node_modules/jquery/dist/jquery.min.js"></script>

before my jQuery code:

<script>window.jQuery = window.$ = require('jquery');</script>

I found this solution in this article; I have already tried this example in Electron's documentation but to no avail.

Please let me know of there is any information missing.

Alexander Leithner
  • 3,169
  • 22
  • 33
mano
  • 13
  • 3
  • Does this answer your question? [Electron: jQuery is not defined](https://stackoverflow.com/questions/32621988/electron-jquery-is-not-defined) – tpikachu Jun 06 '20 at 09:12
  • Yes! For the most part. @AlexanderLeithner is right by stating that I need to get more familiar with the overall electron structure and processes. For now I will have to learn more and come back to this issue later. – mano Jun 07 '20 at 10:11

1 Answers1

2

You're confusing your main and renderer processes. With Electron, all code that is responsible for your UI, i.e. the JavaScript attached to the HTML loaded in the BrowserWindows run in renderer processes, all other code, which, for example, is responsible for opening the windows or for setting up you app runs in the main process.

In this main process, you cannot use DOM-specific globals because the main process is a pure Node.js thing. What you wanted to do with jQuery, i.e.

$(document).ready(function () {
  console.log("hi");
});

won't work nonetheless, because document is not defined in the main process. Also, the main process' environment is detached from your renderer process' (which is why you must use IPC to communicate between them) and thus $ is not defined in your main.js because you define it in the renderer HTML.

If you instead put the following at the end of your HTML (or even your renderer.js you include at the very end of your HTML) file, you might get the result you were looking for:

<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script>
    window.jQuery = window.$ = require('jquery');
    const $ = window.jQuery;
    $(document).ready(function () {
        console.log("hi");
    });
</script>
<script src="./renderer.js"></script>

After all, I'd suggest to familiarise yourself with the Electron architecture by digging into Electron's documentation, such as this article because there is no much more that can go wrong when not familiar with the main/renderer design principle which can be easily fixed by simply understanding this design.

Alexander Leithner
  • 3,169
  • 22
  • 33
  • Thank you for the quick response!! I will take your advise and learn more about electron. It is already very helpful was you wrote, because I was not familiar with most of the terms you mentioned to decribe my problem. – mano Jun 07 '20 at 10:14