1
votes

I get an error saying "Uncaught ReferenceError: require is not defined" when opening a child window. I am using an async message to the main process to create a child window for the main app window on a button press from the main renderers script. I have access to node in the main renderer script. I wanted some node libraries in the script for the child window but I run into a nodeIntegration problem. I have it set to true on the main render, as well as the child render. I can access node features in the script for the primary html render but not child. I think I may be structuring things incorrectly for an electron app. Here is the relevant code:

index.js (main renderer's script that sends message, called on button press)

function addImage(){
    ipcRenderer.send('add-image-req', 'testID');
}

main.js snippet

function createWindow () {
  const win = new BrowserWindow({
    width: 1200,
    height: 900,
    frame: false,
    webPreferences: {
      nodeIntegration: true,
      nodeIntegrationInSubFrames: true,
      nodeIntegrationInWorker: true,
      contextIsolation: false,
      enableRemoteModule: true
      //preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('./assets/html/index.html')
  win.webContents.openDevTools()

  /*
  var menu = Menu.buildFromTemplate([
      {
          label : 'File',
          submenu : [
              {
                  label : "Exit",
                  click() {
                      app.quit()
                  }
              }
          ]
      }
  ])

  Menu.setApplicationMenu(menu)
  */
  Menu.setApplicationMenu(null)

  ipcMain.on("add-image-req", (event, arg) => {
    console.log(arg);
    const child = new BrowserWindow({
      parent: win,
      nodeIntegration: true,
      contextIsolation: false                             
    })
  
  
    child.loadFile("./assets/html/image.html")
    child.webContents.openDevTools()
  })
}

image.js (script for image.html page, the child)

const path = require("path");

If I am completely structuring things incorrectly, please let me know.

EDIT with Minimal Reproducibility

Create a new folder for the project and in the terminal do a

npm init -y
npm install electron

Then make the following 5 files:

  1. main.js
  2. index.html
  3. index.js
  4. image.html
  5. image.js

Go into the created package.json and change the "main" key to "main.js". Change the "scripts" key to "start" : "electron .".

The following is what each of the scripts should contain. I will put minimal code to reproduce in them.

main.js:

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


function createWindow () {
  const win = new BrowserWindow({
    width: 1200,
    height: 900,
    frame: false,
    webPreferences: {
      nodeIntegration: true,
      nodeIntegrationInSubFrames: true,
      nodeIntegrationInWorker: true,
      contextIsolation: false,
      enableRemoteModule: true
      //preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('./index.html')
  win.webContents.openDevTools()

  /*
  var menu = Menu.buildFromTemplate([
      {
          label : 'File',
          submenu : [
              {
                  label : "Exit",
                  click() {
                      app.quit()
                  }
              }
          ]
      }
  ])

  Menu.setApplicationMenu(menu)
  */
  Menu.setApplicationMenu(null)

  ipcMain.on("add-image-req", (event, arg) => {
    console.log(arg);
    const child = new BrowserWindow({
      parent: win,
      nodeIntegration: true,
      contextIsolation: false                             
    })
  
  
    child.loadFile("./image.html")
    child.webContents.openDevTools()
  })
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>index</title>
</head>
<body>
    <button>Click</button>
    <script src="./index.js"></script>
</body>
</html>

index.js:

const { ipcRenderer } = require('electron')

document.querySelector("button").addEventListener('click', () => {
    ipcRenderer.send('add-image-req', 'testID')
})

image.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <a href="">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi adipisci impedit voluptatibus numquam consectetur sapiente possimus earum nobis et, molestiae minus ipsam. Dolore doloremque quia et assumenda maiores? Numquam, nostrum.</a>
    <script src="./image.js"></script>
</body>
</html>

image.js:

const path = require("path");

Then try running with npm start and an error should appear when clicking the button.

1
Can you explain where that error shows up? Do you see it in the dev tools? What Electron version are you using? Thank you for including your code but stripping it down to a minimal reproducible example would be better. - Joshua
Once I click the button to open the child window, the error at the top "Uncaught ReferenceError: require is not defined" occurs in the dev tools console in the child window. The line is the one shown in the post when I require path - sal
Thanks, a minimal reproducible example would still be really helpful stackoverflow.com/help/minimal-reproducible-example - Joshua
Hey bud, I made the edit. Please check it out and let me know what you think. Really appreciate the help! - sal

1 Answers

0
votes

nodeIntegration Is a sub option of webPreferences and needs to be set like this:

const child = new BrowserWindow({
  parent: win,
  webPreferences:  { // <- You need to add this option.
    nodeIntegration: true,
    contextIsolation: false
  }
})

nodeIntegration and contextIsolation should be set inside of webPreferences.