Raphael10
Raphael10

Reputation: 3104

require is not defined in a Electron-React-Webpack-Typescript app with ipcRenderer.on

In an Electron-React-Webpack-Typescript app, when inserting into /src/renderer.ts these lines:

ipcRenderer.on('messageFromMain', (event, message) => {
  console.log(`This is the message from the second window sent via main: ${message}`);
});

I get this error:

enter image description here

This is the entire /src/renderer.ts file:

import './app';

console.log('renderer.js is so happy to say you 👋 hello....');

import { ipcRenderer, BrowserWindow } from 'electron';

ipcRenderer.on('messageFromMain', (event, message) => {
  console.log(`This is the message from the second window sent via main: ${message}`);
});

Based on what I found here: // How to import the electron ipcRenderer in a react / webpack 2 setup , I've also put in tools/webpack/webpack.plugins.js :

const webpack = require('webpack');

module.exports = [
  new ForkTsCheckerWebpackPlugin(),
 new webpack.ExternalsPlugin('commonjs', [
    'electron'
  ])
];

I tried to import electron in renderer.ts as a window component:

const electron = window.require('electron');

But got:

window.require is not a function

It must be something related to the interaction among electron, react and webpack, but I didn' find any solution yet.

With

webPreferences: {
  nodeIntegration: true, // Changed 
  enableRemoteModule: false,
  contextIsolation: false, // Changed
  nodeIntegrationInWorker: false,
  nodeIntegrationInSubFrames: false,
  preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},

it doesn't give require is not defined

when inserting in renderer.ts:

ipcRenderer.on('messageFromMain', (event, message) => {
  console.log(`This is the message from the second window sent via main: ${message}`);
});

I tried to import ipcRenderer in preload.js as follows:

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

But I get

TS2339: Property 'ipcRenderer' does not exist on type 'Window & typeof globalThis'.
window.ipcRenderer = require('electron').ipcRenderer;
   |        ^^^^^^^^^^^

Following these indications: https://github.com/electron/electron/issues/9920#issuecomment-672449613 I also handled ipcRenderer in preload.js as follows :

import { ipcRenderer, IpcRenderer } from 'electron'

declare global {
  namespace NodeJS {
    interface Global {
      ipcRenderer: IpcRenderer
    }
  }
}

// Since we disabled nodeIntegration we can reintroduce
// needed node functionality here
process.once('loaded', () => {
  global.ipcRenderer = ipcRenderer
})

But I get the same error in renderer.ts:

ERROR in src/renderer.ts:14:24
TS2304: Cannot find name 'ipcRenderer'.

So.. the hurdle can be expressed as: how to keep for security purposes

nodeIntegration:false,
contextIsolation: true,

and being able in the same time to import ipcRenderer in renderer.ts? There must be a way to make renderer.ts and main.ts communicate with each other, while keeping the environment as much as secure as possible.

Upvotes: 3

Views: 2015

Answers (1)

Raphael10
Raphael10

Reputation: 3104

Yes. Now it seems working with:

in main.js

webPreferences: {
  nodeIntegration: false,
  enableRemoteModule: false,
  contextIsolation: true,
  nodeIntegrationInWorker: false,
  nodeIntegrationInSubFrames: false,
  preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},

preload.js :

import { ipcRenderer, contextBridge } from 'electron';

contextBridge.exposeInMainWorld(
  'electron',
  {
    doThing: () => ipcRenderer.send('do-a-thing')
  }
)

index.d.ts :

declare interface Window {
  electron: {
    doThing(): void
  }
}

and renderer.ts :

import './app';

console.log('renderer.js is so happy to say you 👋 hello....');

window.electron.doThing();

Upvotes: 2

Related Questions