Skip to content



NodeJS »

Electron - Build JavaScript-based cross-platform applications

Electron is a framework for building desktop applications using JavaScript, HTML, and CSS, by embedding Chromium and Node.js into applicatipon binary. Electron allows you to maintain one JavaScript codebase and create cross-platform apps.


Electron#

Electron is a framework for building desktop applications using JavaScript, HTML, and CSS, by embedding Chromium and Node.js into applicatipon binary. Electron allows you to maintain one JavaScript codebase and create cross-platform apps.

To use Electron, you need to install Node.js. We recommend that you use the latest LTS version available.

Installation#

Create a new NodeJS project:

mkdir my-electron-app && cd my-electron-app
npm init

The interactive init command will prompt you to set some fields in your config. There are a few rules to follow for the purposes of this tutorial:

  • entry point should be main.js.
  • author and description can be any value, but are necessary for app packaging.

Install electron:

npm install --save-dev electron

then add a start command:

{
  "scripts": {
    "start": "electron ."
  }
}

How Electron works#

Electron inherits its multi-process architecture from Chromium, which makes the framework architecturally very similar to a modern web browser.

Window process#

The entry point of any Electron application is its main.js script. This script controls the main process, which runs in a full Node.js environment and is responsible for controlling your app’s lifecycle, displaying native interfaces, performing privileged operations, and managing renderer processes (more on that later).

Electron will create a Browser Window which will load a web page to make its UI.

main.js
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

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

Normally, an index.html wil be provided:

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
  </body>
</html>

Renderer process#

Each Electron app spawns a separate renderer process for each open BrowserWindow (and each web embed). As its name implies, a renderer is responsible for rendering web content.

The webpage can use JavaScript to render its content freely. It is the point to use a JavaScript framework for UI, such as VueJS.

Access NodeJS

Renderer processes can be spawned with a full Node.js environment for ease of development. Historically, this used to be the default, but this feature was disabled for security reasons.

Preload scripts contain code that executes in a renderer process before its web content begins loading. These scripts run within the renderer context, but are granted more privileges by having access to Node.js APIs.

A preload script can be attached to the main process in the BrowserWindow constructor’s webPreferences option.

main.js
const { BrowserWindow } = require('electron')
//...
const win = new BrowserWindow({
  webPreferences: {
    preload: 'path/to/preload.js',
    nodeIntegration: false,
    contextIsolation: true,
  },
})
//...

Although preload scripts share a window global with the renderer they’re attached to, you cannot directly attach any variables from the preload script to window because of the contextIsolation default.

Context Isolation means that preload scripts are isolated from the renderer’s main world to avoid leaking any privileged APIs into your web content’s code.

Instead, use the contextBridge module to accomplish this securely:

preload.js
import {contextBridge, ipcRenderer} from 'electron';

contextBridge.exposeInMainWorld('electron', {
  ipcRenderer: ipcRenderer,
})

Then the electron object can be use in render process, for example:

electron.ts
import { IpcRenderer } from 'electron'

const ipcRenderer = window.electron.ipcRenderer as IpcRenderer

export {
  ipcRenderer,
}

Here is the framework layer:

Electron Appliction Framework

Electron and VueJS#

At this step, we will change the index page to load VueJS:

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hello World!</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.ts"></script>
  </body>
</html>

This index page will call to a script main.ts to initialize VueJS module which, in turn, creates an VueJS Renderer Application:

main.ts
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App);

app.mount('#app');

The VueJS application takes the #app element to render UI.

Electron Vue Template

This repo electron-vue-template hosts a Simple Vue3 + Electron starter template in TypeScript, including ViteJS and Electron Builder.

Comments