Cannot find module 'dialog'


#1

node and electron newbie here, sorry for the basicness of my question.

i’m reading the book “Developing an Electron Edge”.

in chapter’s 5 index.js

the code below seems to generate a “cannot find module ‘dialog’” error

const remote = require(‘electron’).remote;
const dialog = remote.require(‘dialog’);

but when i changed the code to:

const remote = require(‘electron’).remote;
const { dialog } = require(‘electron’).remote;

the error went away and the markdown file editor app being demo’d worked!!

my question: what’s the difference between

const dialog = remote.require(‘dialog’);

vs

const { dialog } = require(‘electron’).remote;

my environment: node version 8.3.0, electron 1.7.5 (although from the book’s downloaded package.json file, the book authors were using a much older “electron-prebuilt”: “^0.36.8” – the book was published may 2016) and my os is windows 10.

thanks for any help / explanation!


#2

That’s called a “destructuring assignment”, and it is equivalent to:

const dialog = require('electron').remote.dialog;

remote.require() is used to require a module in the main process, it would appear that doesn’t work for built-in modules such as dialog.

Since you’re new to Electron I should warn you that while the remote module may seem like the simplest way to manage inter-process control flow it makes it all too easy to shoot yourself in the foot if you use it to access main-process modules in the renderer process.


#3

Sounds scary… and since most examples I see liberally invoke remote I’m not sure I know how to avoid it. Care to explain further?


#4

The docs use remote because it’s a concise way to demonstrate the API being documented. I suggest using the async IPC (ipcMain/ipcRenderer) in most cases, let’s take dialog.showOpenDialog() as an example:

// main process
const { BrowserWindow, dialog, ipcMain } = require('electron')

ipcMain.on('open-file-prompt', (event, options) => {
  const parentWindow = (process.platform !== 'darwin')
                     ? BrowserWindow.fromWebContents(event.sender) : null
  
  dialog.showOpenDialog(parentWindow, options, fileNames => {
    const fileName = (fileNames && (fileNames.length > 0)) ? fileNames[0] : null
    event.sender.send('file-prompt-result', fileName)
  })
})
// renderer process
const { ipcRenderer } = require('electron')

function promptForFile() {
  return new Promise((resolve, reject) => {
    ipcRenderer.once('file-prompt-result', (event, fileName) => resolve(fileName))
    const options = { /* ... */ }
    ipcRenderer.send('open-file-prompt', options)
  })
}

promptForFile().then(fileName => {
  if (fileName) {
    // do something with the filename
  }
}

That’s the gist of it.


#5

Hi! I follow your code with a CRA (Create-React-App) script. When I run the code I get some complaints about fs. See Screenshot attached 04B2A782632C4009B52C92A05F097DF0|661x430


#6

04B2A782632C4009B52C92A05F097DF0