guide add electron - devonfw/devon4ng GitHub Wiki
This cookbook recipe explains how to integrate Electron in an Angular 10+ application. Electron is a framework for creating native applications with web technologies like JavaScript, HTML, and CSS. As an example, very well known applications as Visual Studio Code, Atom, Slack or Skype (and many more) are using Electron too.
ℹ️
|
At the moment of this writing Angular 11.2.0, Electron 11.2.3 and Electron-builder 22.9.1 were the versions available. |
Here are the steps to achieve this goal. Follow them in order.
There are two different approaches to add the dependencies in the package.json
file:
-
Writing the dependencies directly in that file.
-
Installing using
npm install
oryarn add
.
❗
|
Please remember if the project has a package-lock.json or yarn.lock file use npm or yarn respectively.
|
In order to add the dependencies directly in the package.json
file, include the following lines in the devDependencies
section:
"devDependencies": {
...
"electron": "^11.2.3",
"electron-builder": "^22.9.1",
...
},
As indicated above, instead of this npm install
can be used:
$ npm install -D electron electron-builder
Or with yarn
:
$ yarn add -D electron electron-builder
In order to initiate electron in an angular app we need to modify the tsconfig.json
file and create a tsconfig.serve.json
and a tsconfig.base.json
in the root folder.
This file needs to be modified to create references to ./src/tsconfig.app.json
and ./src/tsconfig.spec.json
to support different configurations.
{
"files": [],
"references": [
{
"path": "./src/tsconfig.app.json"
},
{
"path": "./src/tsconfig.spec.json"
}
]
}
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "../app",
"module": "es2015",
"baseUrl": "",
"types": []
},
"include": [
"**/*.ts",
],
"exclude": [
"**/*.spec.ts"
],
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true,
"preserveWhitespaces": true
}
}
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "../spec",
"module": "commonjs",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts",
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
],
"exclude": [
"dist",
"release",
"node_modules"
]
}
This is shared between tsconfig.app.json
and tsconfig.spec.json
and it will be extended on each config file.
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"es2016",
"es2015",
"dom"
]
},
"files": [
"electron-main.ts"
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
],
"exclude": [
"node_modules"
]
}
In the root, tsconfig.serve.json
needs to be created. This typescript config file is going to be used when we serve electron:
{
"compilerOptions": {
"outDir": ".",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
},
"include": [
"electron-main.ts"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
In order to configure electron builds properly we need to create a new json on our application, let’s call it electron-builder.json. For more information and fine tuning please refer to the Electron Builder official documentation.
The contents of the file will be something similar to the following:
{
"productName": "devon4ngElectron",
"directories":{
"output": "./builder-release"
},
"win": {
"icon": "dist/assets/icons",
"target": [
"portable"
]
},
"mac": {
"icon": "dist/assets/icons",
"target": [
"dmg"
]
},
"linux": {
"icon": "dist/assets/icons",
"target": [
"AppImage"
]
}
}
There are two important things in this files:
-
"output": this is where electron builder is going to build our application
-
"icon": in every OS possible there is an icon parameter, the route to the icon folder that will be created after building with angular needs to be used here. This will make it so the electron builder can find the icons and build.
angular.json
has to to be modified so the project is build inside /dist without an intermediate folder.
{
"architect": {
"build": {
"outputPath": "dist"
}
}
}
In order to use electron, a file needs to be created at the root of the application (main.ts
). This file will create a window with different settings checking if we are using --serve
as an argument:
import { app, BrowserWindow } from 'electron';
import * as path from 'path';
import * as url from 'url';
let win: any;
const args: any = process.argv.slice(1);
const serve: any = args.some((val) => val === '--serve');
const createWindow:any = ()=>{
// Create the browser window.
win = new BrowserWindow({
fullscreen: true,
webPreferences: {
nodeIntegration: true,
}
});
if (serve) {
require('electron-reload')(__dirname, {
electron: require(`${__dirname}/node_modules/electron`)
});
win.loadURL('http://localhost:4200');
} else {
win.loadURL(
url.format({
pathname: path.join(__dirname, 'dist/index.html'),
protocol: 'file:',
slashes: true
})
);
}
if (serve) {
win.webContents.openDevTools();
}
// Emitted when the window is closed.
win.on('closed', () => {
// Dereference the window object, usually you would store window
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
// tslint:disable-next-line:no-null-keyword
win = null;
});
}
try {
// 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 OS X 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 OS X 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();
}
});
} catch (e) {
// Catch Error
// throw e;
}
Inside package.json
the electron window that will be transformed to electron-main.js
when building needs to be added.
{
....
"main": "electron-main.js",
"scripts": {...}
....
}
The scripts
section in the package.json
can be improved to avoid running too verbose commands. As a very complete example we can take a look to the My Thai Star’s scripts
section and copy the lines useful in your project. In any case, at least we recommend to add the following lines:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"electron:tsc": "tsc -p tsconfig.serve.json",
"electron:run": "npm run electron:tsc && ng build --base-href ./ && npx electron .",
"electron:serve": "npm run electron:tsc && npx electron . --serve",
"electron:pack": "npm run electron:tsc && electron-builder --dir --config electron-builder.json",
"electron:build": "npm run electron:tsc && electron-builder --config electron-builder.json build"
},
The electron:
scripts do the following:
-
electron:tsc
: Compiles electron TS files. -
electron:run
: Serves Angular app and runs electron. -
electron:serve
: Serves electron with an already running angular app (i.e. ang serve
command running on another terminal). -
electron:pack
: Packs electron app. -
electron:build
: Builds electron app.
Creating an Electron app is very easy and straight-forward if you are using Nx CLI. As a pre-requisite, you should already have an application in your Nx workspace which you want to run as a front-end in your Electron app. (You can follow this guide if you want to get started with Nx).
Follow the steps below to develop an Electron app in your Nx workspace:
Install nx-electron
using the command:
npm install -D nx-electron
electron
and nx-electron
as dev dependencies to your Nx workspace. This will help us generate our Electron app in the next step.
Once you have installed nx-electron
, you can generate your electron app using the command:
nx g nx-electron:app <electron-app-name> --frontendProject=<frontend-app-name>
And that is it! You have generated your Electron app already. All the configuration files (tsconfig.*
) are generated for you under <electron-app-name> in your Nx workspace.
You can use this command to serve your Electron app:
nx run-many --target=serve --projects=<frontend-app-name>,<electron-app-name> --parallel
If you see a blank application, it is because the Electron app was served before the front-end was served. To avoid this, you can serve the front-end and back-end separately, (that is, serve the back-end only after the front-end is served).
The command for building your Electron app in Nx is similar to the serve
command above, you only change the target from serve
to build
:
nx run-many --target=build --projects=<frontend-app-name>,<electron-app-name> --parallel
Make sure you have build your app before you try to package it using the following command:
nx run <electron-app-name>:package [--options]
You can find a working example of an Electron app in devon4ts-samples.