2

I am having trouble with my Electron app. I had it working about 9 months ago, but now the custom minimise and maximise buttons I made are not functioning properly.

Here is my file structure

node_modules
    ...
web
    css
        main.css
    html
        index.html
    images
        ...
    js
        index.js
    themes
        ...
main.js
package.json
package-lock.json
require.js

And here is the contents of index.html

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="../css/main.css">
        <style type="text/css">* {visibility: hidden;}</style>
        <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,700" rel="stylesheet">
        <link rel="icon" href="../images/favicon-32x32.png" />
    </head>
    <body>
        <div id="wrapper">
            <div id="title-bar">
                <div id="title-bar-btns">
                    <button id="min-btn" onclick="window_minimise()">&#x2014;</button>
                    <button id="close-btn" onclick="window_close()">&#x2715;</button>
                </div>
            </div>
        ...
        </div>
        <script>
            // You can also require other files to run in this process
            require('../../renderer.js')
        </script>
        <script src="../js/index.js" type="text/javascript"></script>
    </body>
</html>

And index.js

...
const {BrowserWindow} = require('electron').remote;

  function window_minimise(){
      let window = BrowserWindow.getCurrentWindow();
      window.minimize();
  }

  function window_close(){
      let window = BrowserWindow.getCurrentWindow();
      window.close();
  }
...

And here is my main.js file

const {app, BrowserWindow} = require('electron')

let mainWindow

function createWindow () {

  let mainWindow = new BrowserWindow({
      width: 1200,
      height: 748,
      icon:'web/images/favicon-32x32.png',
      resizable: false,
      frame: false,
      show: false,
      backgroundColor: '#171717',
      webPreferences: {
          nodeIntegration: true
      }
  })

  mainWindow.once('ready-to-show', () => {
  mainWindow.show()
})
  mainWindow.setMenu(null);

  mainWindow.loadURL('http://localhost:8000/html/index.html')

  mainWindow.on('closed', function () {
    mainWindow = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

app.on('activate', function () {
  if (mainWindow === null) createWindow()
})

When I click minimise or maximise, nothing happens. So I went to http://localhost:8000/html/index.html and checked the console, and I saw these errors

Uncaught ReferenceError: require is not defined at index.html:137

Uncaught ReferenceError: require is not defined at index.js:110

I am using electron version 5.0.2 by the way.

If someone could help me resolve this, that would be wonderful.

Thanks.

EDIT: The errors I mentioned above are shown when the page loads, and this error is shown when I click minimise

Uncaught ReferenceError: Cannot access 'BrowserWindow' before initialization at window_minimise (index.js:113) at HTMLButtonElement.onclick (index.html:18)

EDIT2: I think the issue is that eel (the code that allows me to interface python with my electron app) requires the webpage to be run on localhost, and thus node features such as require do not work. I go into a bit more detail in a GitHub issue here: github.com/ChrisKnott/Eel/issues/147

Jack P
  • 469
  • 1
  • 6
  • 16
  • Look's like you can find answere [here](https://stackoverflow.com/questions/55093700/electron-5-0-0-uncaught-referenceerror-require-is-not-defined) – Timofey Goncharov May 25 '19 at 10:24
  • @TimofeyGoncharov If you read my post you would realise I already have nodeIntegration set to true – Jack P May 25 '19 at 10:26
  • please provide the full version of index.js since errors refer to specific lines on that file – GJCode May 25 '19 at 10:38
  • @GJCode I have provided the lines surrounding and including where the error is – Jack P May 25 '19 at 10:39
  • you cannot use require in a normal browser. JS run in a sandbox in a normal browser and require makes use of the filesystem that is not accessible from a browser. What electron does is wrap your app in chromium browser and run js outside that sandbox and this is why with electron (and node) you can use require and the filesystem. This is way you get that errors on your console, they are not related to your problem – GJCode May 25 '19 at 10:50
  • @GJCode Thanks, so how can I see the errors that might be preventing it from working? – Jack P May 25 '19 at 10:51
  • you can show a dialog with exception thrown from code that can cause an exception or you can take a look at a debugger https://electronjs.org/docs/tutorial/debugging-main-process – GJCode May 25 '19 at 10:56
  • @GJCode I'm not really sure what you mean with the first point. With regards to the second point, the problem is that I don't start my app via `npm start` or `electron .` as it uses an eel wrapper which then executes the electron app, but allows me to run python on it. So, I execute a python file to run the app. – Jack P May 25 '19 at 10:58
  • electron is tought as a node library so use npm start is very reccomanded, anyway if you have a function: doSomething() that can throws an exception in the catch clause you can show a popup with the stack of the error for example – GJCode May 25 '19 at 11:03
  • @GJCode I put a try catch around it, then told it to print that error in python and it just prints {}. – Jack P May 25 '19 at 11:09
  • @GJCode I did an alert instead and the error was `ReferenceError: require is not defined`... – Jack P May 25 '19 at 11:10
  • Where? As I said you cannot use require on client side – GJCode May 25 '19 at 11:47
  • @GJCode I ran the electron app and put the alert in there, so that error is the problem. – Jack P May 25 '19 at 11:50
  • I mean in what line of the code? Remove require from the html and keep in mind that the html should be used only for presentation – GJCode May 25 '19 at 11:57
  • @GJCode I put it around window_minimise(). I don't mean to be rude, but I'm not sure you are right - the electron-quick-start repo does it exactly like I have done. – Jack P May 25 '19 at 12:05
  • yeah but you should run electron in a "normal" way not through python, not in your browser – GJCode May 25 '19 at 12:19
  • @GJCode I did not run it through my browser this time... – Jack P May 25 '19 at 12:20
  • @GJCode `require` **is** the problem. – Jack P May 25 '19 at 12:21
  • at index.html 137? – GJCode May 25 '19 at 12:25
  • @GJCode Yes, `require('../../renderer.js')` and `const {BrowserWindow} = require('electron').remote;` are causing the errors. Or at least I'm certain the second one is, I can't check for errors in the HTML file afaik. – Jack P May 25 '19 at 12:28
  • once again the problem as stated is that require do not exists in app environment, as I said require can only be used "server side" because it access the filesystem, this not mean that you are making some syntax mistakes nor that you can solve by a workaround, you have to provide to your app a good environment and for electron is chromium, but you're tryng to use python (still not sure why) and you are using logic not referred to dom manipulation in your html (not a good practice in this case) – GJCode May 25 '19 at 12:34
  • @GJCode You are not listening to what I am saying. Python is still executing electron. The error is being shown within electron, and it is a problem with `require`. If it helps you to understand, just ignore the Python part. – Jack P May 25 '19 at 12:37
  • I think that you are not listening, **where** electron app is executed is the only difference. Electron is just a js library so you are using javascript, but some javascript new features like require can run only out of the sendbox, so the **same code** can throws exceptions depending on where it is executed. If you use a python process to execute your app in what way you are sure that you have what js needs to execute server side scripts? – GJCode May 25 '19 at 12:44
  • @GJCode Thanks for your responses thus far but I don't think you can help me. – Jack P May 25 '19 at 12:45

2 Answers2

6

All you need to do is add contextIsolation: false after nodeIntegration: true in the webPreferences object

K4S3
  • 163
  • 2
  • 11
1

Change your index.js file as follows. Then use nodeRequire instead of require keyword.

  initNodeRequire();
  const {BrowserWindow} = nodeRequire('electron').remote;

  function window_minimise(){
      let window = BrowserWindow.getCurrentWindow();
      window.minimize();
  }

  function window_close(){
      let window = BrowserWindow.getCurrentWindow();
      window.close();
  }

  function initNodeRequire(){
       window.nodeRequire = require;
       delete window.require;
       delete window.exports;
       delete window.module;
  }
Aravinda Meewalaarachchi
  • 2,551
  • 1
  • 27
  • 24
  • Thanks for your response, Unfortunately, I still get these errors: `Uncaught ReferenceError: require is not defined at index.html:137`, `Uncaught ReferenceError: require is not defined at initNodeRequire (index.js:123) at index.js:109`, and when I click minimise `Uncaught ReferenceError: BrowserWindow is not defined at window_minimise (index.js:113) at HTMLButtonElement.onclick (index.html:18)`. – Jack P May 27 '19 at 16:38
  • Although I'm not sure about this, because I think `require` is a node thing which will not run in the browser, and even if I'm viewing the console via devtools for electron, that is really just the localhost instance. Even so, the buttons still are not working. – Jack P May 27 '19 at 16:42
  • I think the issue is that eel (the code that allows me to interface python with my electron app) requires the webpage to be run on localhost, and thus node features such as `require` do not work. I go into a bit more detail in a GitHub issue here: https://github.com/ChrisKnott/Eel/issues/147 – Jack P May 27 '19 at 17:07