• This repository has been archived on 17/Jun/2020
  • Stars
    star
    430
  • Rank 101,083 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 8 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

DEPRECATED: Execute JavaScript in remote Electron processes, but more betterer

DEPRECATED: electron-remote: an asynchronous 'remote', and more

No Maintenance Intended

This project is no longer maintained, pull requests are no longer being reviewed or merged and issues are no longer being responded to.


electron-remote provides an alternative to Electron's remote module based around Promises instead of synchronous execution. It also provides an automatic way to use BrowserWindows as "background processes" that auto-scales based on usage, similar to Grand Central Dispatch or the .NET TPL Taskpool.

The Quickest of Quick Starts

Calling main process modules from a renderer
import { createProxyForMainProcessModule } from 'electron-remote';

// app is now a proxy for the app module in the main process
const app = createProxyForMainProcessModule('app');

// The difference is all methods return a Promise instead of blocking
const memoryInfo = await app.getAppMemoryInfo();
Calling code in other windows
import { createProxyForRemote } from 'electron-remote';

// myWindowJs is now a proxy object for myWindow's `window` global object
const myWindowJs = createProxyForRemote(myWindow);

// Functions suffixed with _get will read a value
userAgent = await myWindowJs.navigator.userAgent_get()
Renderer Taskpool
import { requireTaskPool } from 'electron-remote';

const myCoolModule = requireTaskPool(require.resolve('./my-cool-module'));

// This method will run synchronously, but in a background BrowserWindow process
// so that your app will not block
let result = await myCoolModule.calculateDigitsOfPi(100000);

But I like Remote!

Remote is super convenient! But it also has some downsides - its main downside is that its action is synchronous. This means that both the main and window processes will wait for a method to finish running. Even for quick methods, calling it too often can introduce scroll jank and generally cause performance problems.

electron-remote is a version of remote that, while less ergonomic, guarantees that it won't block the calling thread.

Using createProxyForRemote

createProxyForRemote is a replacement for places where you would use Electron's executeJavaScript method on BrowserWindow or WebView instances - however, it works a little differently. Using a new feature in ES2015 called proxy objects, we create an object which represents the window object on a remote context, and all method calls get sent as messages to that remote instead of being run immediately, which feels very similar to the remote Electron module.

This provides a number of very important advantages:

  • createProxyForRemote uses asynchronous IPC instead of blocking
  • Parameters are serialized directly, so you don't have to try to build strings that can be evald, which is a dangerous endeavor at best.
  • Calling methods on objects is far more convenient than trying to poke at things via a remote eval.

How do I get properties if everything is a Promise tho???

Astute observers will note, that getting the value of a property is always a synchronous operation - to facilitate that, any method with _get() appended to it will let you fetch the value for the property.

import { createProxyForRemote } from 'electron-remote';

// myWindowJs is now a proxy object for myWindow's `window` global object
const myWindowJs = createProxyForRemote(myWindow);

// Functions suffixed with _get will read a value
myWindowJs.navigator.userAgent_get()
  .then((agent) => console.log(`The user agent is ${agent}`));

But do this first!

Before you use createProxyForRemote, you must call initializeEvalHandler() in the target window on startup. This sets up the listeners that electron-remote will use.

Bringing it all together

// In my window's main.js
initializeEvalHandler();
window.addNumbers = (a,b) => a + b;


// In my main process
let myWindowProxy = createProxyForRemote(myWindow);
myWindowProxy.addNumbers(5, 5)
  .then((x) => console.log(x));

>>> 10

Using createProxyForMainProcessModule

This is meant to be a drop-in replacement for places you would have used remote in a renderer process. It's almost identical to createProxyForRemote, but instead of evaling JavaScript it can only call methods on main process modules. It still has all the same benefits: asynchronous IPC instead of an ipc.sendSync.

Here Be Dragons

electron-remote has a number of significant caveats versus the remote module that you should definitely be aware of:

  • Remote values must be Serializable

Objects that you return to the calling process must be serializable (i.e. you can call JSON.stringify on it and get a valid thing)- this means that creating Classes won't work, nor will return objects like BrowserWindows or other Electron objects. For example:

let myWindowProxy = createProxyForRemote(myWindow);

// XXX: BAD - HTML elements aren't serializable
let obj = myWindowProxy.document.createElement('h1');
  • Remote event listeners aren't supported

Anything that involves an event handler isn't going to work:

// XXX: BAD - You can't add event handlers
myWindowProxy.document.addEventListener('onBlur', (e) => console.log("Blur!"));

The Renderer Taskpool

Renderer Taskpools provide an automatic way to use BrowserWindows as "background processes" that auto-scales based on usage, similar to Grand Central Dispatch or the .NET TPL Taskpool. This works by allowing you to provide a Module that you'd like to load in the remote processes, which will be loaded and unloaded on the fly according to demand.

Let's look at the example again:

import { requireTaskPool } from 'electron-remote';

const myCoolModule = requireTaskPool(require.resolve('./my-cool-module'));

// This method will run synchronously, but in a background BrowserWindow process
// so that your app will not block
let result = await myCoolModule.calculateDigitsOfPi(100000);

By default, requireTaskPool will create up to four background processes to concurrently run JS code on. As these processes become busy, requests will be queued to different processes and wait in line implicitly.

More Dragons

Since requireTaskPool will create and destroy processes as needed, this means that global variables or other state will be destroyed as well. You can't rely on setting a global variable and having it persist for a period of time longer than one method call.

The remote-ajax module

One module that is super useful to have from the main process is a way to make network requests using Chromium's networking stack, which correctly does things such as respecting the system proxy settings. To this end, electron-remote comes with a convenient wrapper around Rx-DOM's AJAX methods called remote-ajax.

import { requireTaskPool } from 'electron-remote';

const remoteAjax = requireTaskPool(require.resolve('electron-remote/remote-ajax'));

// Result is the object that XmlHttpRequest gives you
let result = await remoteAjax.get('https://httpbin.org/get');
console.log(result.url)

>>> 'https://httpbin.org/get'

See the documentation for Rx-DOM for how these methods work.

Another method that is included is downloadFileOrUrl, which lets you download a file to a target:

/**
 * Downloads a path as either a file path or a HTTP URL to a specific place
 *
 * @param  {string} pathOrUrl   Either an HTTP URL or a file path.
 * @return {string}             The contents as a UTF-8 decoded string.
 */
function downloadFileOrUrl(pathOrUrl, target)

More Repositories

1

electron-builder

A complete solution to package and build a ready for distribution Electron app with โ€œauto updateโ€ support out of the box
TypeScript
13,564
star
2

devtron

[LOOKING FOR MAINTAINERS] An Electron DevTools Extension
JavaScript
1,728
star
3

spectron

DEPRECATED: ๐Ÿ”Ž Test Electron apps using ChromeDriver
JavaScript
1,677
star
4

electron-json-storage

๐Ÿ“ฆ Easily write and read user settings in Electron apps
JavaScript
1,433
star
5

electron-compile

DEPRECATED: Electron supporting package to compile JS and CSS in Electron applications
JavaScript
1,008
star
6

electron-webpack

Scripts and configurations to compile Electron applications using webpack
TypeScript
903
star
7

electron-prebuilt

๐ŸŽ‚ Retired project. See README
JavaScript
760
star
8

electron-webpack-quick-start

A bare minimum project structure to get started developing with electron-webpack.
JavaScript
729
star
9

electron-windows-store

๐Ÿ“ฆ Turn Electron Apps into Windows AppX Packages
JavaScript
678
star
10

electron-installer-windows

Create a Windows package for your Electron app.
JavaScript
470
star
11

electron-installer-debian

Create a Debian package for your Electron app.
JavaScript
377
star
12

electron-wix-msi

๐Ÿ“€ Create traditional MSI installers for your Electron app
TypeScript
319
star
13

electron-installer-dmg

Create DMG installers for your electron apps using appdmg.
JavaScript
298
star
14

electron-spellchecker

Implement spellchecking, correctly
JavaScript
237
star
15

electron-builder-binaries

NSIS
172
star
16

electron-prebuilt-compile

electron-prebuilt with Babel and React built-in
JavaScript
169
star
17

electron-build-service

Package Electron applications in a distributable format on any platform for any platform
Go
138
star
18

electron-forge-templates

Templates bundled with Electron Forge <= 5 to create Electron apps using popular JavaScript frameworks
JavaScript
104
star
19

electron-installer-redhat

Create a Red Hat / RPM package for your Electron app.
JavaScript
81
star
20

electron-installer-snap

Build Snap packages for Electron applications
JavaScript
49
star
21

electrify

Step-by-step wizard to prepare Electron app for distribution, from packaging to auto-update.
TypeScript
48
star
22

electron-installer-zip

Create a ZIP file with support for symlinks required by Electron on macOS
JavaScript
46
star
23

welcome

Organization mission statement and contribution guidelines
45
star
24

electron-compilers

DEPRECATED: Compiler implementations for electron-compile
JavaScript
35
star
25

electron-installer-common

Common functionality for creating Node modules which create distributable Electron apps
JavaScript
9
star
26

electron-forge-container

Docker container for building Electron apps via Electron Forge
Dockerfile
7
star
27

create-electron-app

JavaScript
5
star
28

electron-forge-plugin-compile

Electron Compile plugin for Electron Forge
JavaScript
3
star
29

vue-cli-plugin-electron-forge

@vue/cli plugin to add Electron Forge
3
star