Asked  7 Months ago    Answers:  5   Viewed   74 times

Problem: while developing using Electron, when you try to use any JS plugin that requires jQuery, the plugin doesn't find jQuery, even if you load in the correct path using script tags.

For example,

<body>
<p id="click-me">Click me!</p>
...
<script src="node_modules/jquery/dist/jquery.min.js"></script> //jQuery should be loaded now
<script>$("#click-me").click(() => {alert("Clicked")});</script>
</body>

Running this code above wouldn't work. In fact, open up DevTools, go to the Console view, and click on the <p> element. You should see that function $ is not defined or something to that effect.

 Answers

99

A better and more generic solution IMO:

<!-- Insert this line above script imports  -->
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>

<!-- normal script imports etc  -->
<script src="scripts/jquery.min.js"></script>    
<script src="scripts/vendor.js"></script>    

<!-- Insert this line after script imports -->
<script>if (window.module) module = window.module;</script>

Benefits

  • Works for both browser and electron with the same code
  • Fixes issues for ALL 3rd-party libraries (not just jQuery) without having to specify each one
  • Script Build / Pack Friendly (i.e. Grunt / Gulp all scripts into vendor.js)
  • Does NOT require node-integration to be false

source here

Tuesday, June 1, 2021
 
tiny
answered 7 Months ago
65

As of version 5, the default for nodeIntegration changed from true to false. You can enable it when creating the Browser Window:

app.on('ready', () => {
    mainWindow = new BrowserWindow({
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
        }
    });
});
Saturday, June 5, 2021
 
ioleo
answered 7 Months ago
59

electron-packager was (update: changed in this commit: "refactor: merge electron-packager") used by electron-builder. This article states

If you really want to go to town, take a look at electron-builder which takes the packages produced by electron-packager and creates automated installers.

  • electron-builder example

  • electron-builder React boilerplate project

  • electron-packager React boilerplate project, although there is a GitHub issue to use electron-builder.

Sunday, August 8, 2021
 
KingCrunch
answered 4 Months ago
62

You can call minimize() on the respective BrowserWindow instance. The question is how to best get access to this instance and this, in turn, depends on how you open the windows and where your minimize button is. From your example, I take it that the minimize button is actually in the window you want to close, in that case you can just minimize the focused window, because to when a user clicks the button inside it, the window should currently have the focus:

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

Alternatively you can use BrowserWindow.fromId() to get access to the window in question if, for example, you want to minimize the task window from the other window.

Wednesday, August 11, 2021
 
Noctis
answered 4 Months ago
22

When you have nodeIntegration disabled but aren't using contextIsolation, you could use a preload script to expose a safe version of it on the global object. (Note: you shouldn't expose the entire fs module to a remote page!)

Here's an example of using a preload script in this way:

// main process script
const mainWindow = new BrowserWindow({
  webPreferences: {
    contextIsolation: false,
    nodeIntegration: false,
    preload: './preload.js'
  }
})

mainWindow.loadURL('my-safe-file.html')



// preload.js
const { readFileSync } = require('fs')

// the host page will have access to `window.readConfig`,
// but not direct access to `readFileSync`
window.readConfig = function () {
  const data = readFileSync('./config.json')
  return data
}



// renderer.js
const config = window.readConfig()

If you're only loading local pages, and those pages don't load or execute unsafe dynamic content then you might reconsider the use of contextIsolation for this strategy. If you want to keep contextIsolation on, however (and you definitely should if you have a chance of showing unsafe content), you can only communicate with the preload script with message passing via postMessage.

Here's an example of the same scenario above, but with contextIsolation on and using message passing.

// main process script
const mainWindow = new BrowserWindow({
  webPreferences: {
    contextIsolation: true,
    nodeIntegration: false,
    preload: './preload.js'
  }
})

mainWindow.loadURL('my-unsafe-file.html')



// preload.js
const { readFileSync } = require('fs')

const readConfig = function () {
  const data = readFileSync('./config.json')
  return data
}

window.addEventListener('message', (event) => {
  if (event.source !== window) return
  if (event.data.type === 'request') {
    window.postMessage({ type: 'response', content: readConfig() })
  }
})



// renderer.js
window.addEventListener('message', (event) => {
  if (event.source !== window) return
  if (event.data.type === 'response') {
    const config = event.data.content
  }
})
window.postMessage('request')

While this is definitely more verbose and difficult to deal with (and forces things to be async, because message passing is async), it's also much more secure. A pair of small JS wrappers around the postMessage API could make this easier to work with (e.g. via an RPC-like mechanism), but remember that the whole point of using contextIsolation is because you can't trust the renderer, so your preload script shouldn't trust just any message it gets via the postMessage API — you should always verify the event that you receive to ensure that you trust it.

This slide deck describers in detail why turning off Node integration without using context isolation is not always a good idea.

Monday, November 1, 2021
 
aaki
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share