Integrate your project with Electron

Electron is a platform to develop desktop applications using web technologies like HTML, CSS and JS. Integrate a ng-cli application with Electron is more straightforward that it may seems.

Electron’s two package structure

If you are familiarized with Electron you may remember the two package structure. We will use a similar structure, but with a key difference: In a regular two package structure, the /app/ folder will contains the Electron app. We will name this folder /electron/ and another /app/ folder inside will contains our compiled Angular application.

It may seem like we are using the two package structure, but we are just separating the Electron part from the rest of the application.

Changes in the app configuration

  • Create a script in our Angular application package.json.
1
"electron:start": "ng build --watch -op=electron/app"

This will build the Angular app inside an app folder inside our Electron folder app, and will rebuild on every change.

  • Add the new output folder into .gitignore, in #compiled output section, /electron/app.
  • Modify the base tag of the index.html of our Angular app, as follow:
    1
    <base href="./">

Adding a dot before the slash will allow Electron to find the served files, and without a 404 error will be threw.

This will be all the modifications that we need to integrate the application with Electron.

Creating our Electron app

  • We need to create a electron folder inside our project. Inside we are going to run npm init command to create the Electron package.json. This folder will be our Electron root folder.
  • We add Electron as a development dependency.

    1
    npm install -D electron
  • We create the entry point for our Electron program.

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
const { app, BrowserWindow } = require('electron');
const path = require('path');
const url = require('url');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

function createWindow() {
// Create the browser window.
win = new BrowserWindow({ width: 800, height: 600 });

// and load the index.html of the app.
win.loadURL(
url.format({
pathname: path.join(__dirname, 'app', 'index.html'),
protocol: 'file:',
slashes: true,
}),
);

// Open the DevTools.
win.webContents.openDevTools();

// Emitted when the window is closed.
win.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null;
});
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});

app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow();
}
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

Running the app

  • Open a terminal and move to the Angular project, and run npm run electron:start to start the Angular application.

  • Open a second terminal and move to the electron folder inside the project, and run electron . to start the electron application.

You should see a window with the Angular app running inside of it.

Moving forward

We now have a very simple Angular application running inside of the Electron renderer process. If we modify something of either, the Angular app, or the Electron app, we need to close the Electron window and run the electron . again. This could be optimize using plugins and build systems, but this is the out-the-box behavior of Electron.

You may notice that the entry file of the Electron application is written in vanilla Javascript. This is because Electron runs only vanilla Javascript, and in order to run other language such Typescript, you should use a plugin, such ts-node, or a build system.

Series