My workable project template for Angular Electron
It's not a simple task if you try do doing this first time, there are millions troubles potentially will wait you, I will make some notes to possible troubles, and publish on this page only successful outcome.
Workable project template published to https://github.com/Alex1998100/AngularElectron. This project allow to working with the same project with Browser and with Electron.
- 1. Create Angular project and add Electron library.
- 2. Select way how we going further - to build Elecron app with Webpack or Without Webpack.
- 3. Create two different set of Typescript compilation parameters - (1) to normal Angular start for Browser and embedded bundler and (2) to create bundle to start project as Electron.
- 4. Add Electron features.
- 5. Start project.
- 6. Key features to programming Electron application..
1. Create Angular project and add Electron library.
So, first step is :
# ng new AngularElectron1 # cd AngularElectron1 # npm i --save-dev electron # .\node_modules\.bin\electron -v # ng serve # npx ng serve
After that Angular should working properly and main point "electron" library should appears in package.json. And (!) in Node-Modules folder !! This is version with positive result.
Unfortunately, in most case even reach this point is impossible, because library "electron" not appears in package.json (Trouble#1) or in Node-modules (Trouble#2) appear only library "electron-in-chromium". In this case all further steps will be wrong and will show you fantastic unexpected result (Trouble#3). But when I start this project even Angular not working properly (Trouble#4)
Usually, in my opinion this is possible, because Electron is .EXE application (Note#1) and Global Angular version different than Local version. In this case we need clear NODE cache and update global version (Note#2). Or you start just npx electron (without the dot), instead npx electron . (with dot). Or, I very often forget to change project root to correct folder, "ng serve" should start from folder with "angular.json"
So, this is case with positive result - (1) Angular still working, (2) Electron library appears in package.json, (3) library Electron appears in Node-Modules folder.
2. Select way how we going further - to build Elecron app with Webpack or Without Webpack.
Electron app is ONE Javascript bundle, bot Typescript. Therefore we need to prepare final Javascript bundle, one way is Webpack. I used Webpack in many my projects, fro example in this project MyVault application, in this way all further way started with this adding configuration file webpack.config.js and than use build process and start separately, look more detail in my topic Webpack and Webpack note about Angular Electron.
But in current project I have selected another alternative way - use embedded Angular bundler "moduleResolution": "bundler", but ONLY (!!!) for Angular implementation and use another technique to create bundle in Electron implementation.
This is my key difference WebPack and embedded bundler in Angular, Angular and TSC options:
- difference WebPack and embedded bundler in Angular
- Tsc Compiler "Module" and "outFile/outDir" Options.
- Angular Options
So, we need to provide a couple changing to standard Angular application.
3. Create two different set of Typescript compilation parameters - (1) to normal Angular start for Browser and embedded bundler and (2) to create bundle to start project as Electron.
This is tsc compiler features tsc CLI Options and now we will use important tsc-compiler feature - extend tsconfig.json with two separate parameter set - tsconfig.app.json for normal Angular start with Browser and tsconfig.electron.json- for start Electron desktop app.
So, (1) Rename main.ts to angular-main.ts and
(2) Change Angular project Entry point from main.ts to angular-main.ts in angular.json configuration.Change Angular project Entry point from main.ts to angular-main.ts in angular.json configuration. (JetBrain made this automatically, VS Code need manually change).
1: "browser": "src/angular-main.ts",
(3) Comment embedded Angular bundler in tsconfig.json and add moduleResolution type:
1: /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2: /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3: {
4: "compileOnSave": false,
5: "compilerOptions": {
6: "moduleResolution":"node", // <--- add
7: "outDir": "./dist/out-tsc",
8: "strict": true,
9: "noImplicitOverride": true,
10: "noPropertyAccessFromIndexSignature": true,
11: "noImplicitReturns": true,
12: "noFallthroughCasesInSwitch": true,
13: "skipLibCheck": true,
14: "esModuleInterop": true,
15: "sourceMap": true,
16: "declaration": false,
17: "experimentalDecorators": true,
18: //"moduleResolution": "bundler",
19: "importHelpers": true,
20: "target": "ES2022",
21: "module": "ESNext",
22: "useDefineForClassFields": false,
23: "lib": [
24: "ES2022",
25: "dom"
26: ]
27: },
28: "angularCompilerOptions": {
29: "enableI18nLegacyMessageIdFormat": false,
30: "strictInjectionParameters": true,
31: "strictInputAccessModifiers": true,
32: "strictTemplates": true
33: }
34: }
(4) Modify extension for tsc parameter to Angular compilation tsconfig.app.json, move embedded Angular bundler to extension config and delete all feature files, related to Electron:
1: /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2: /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3: {
4: "extends": "./tsconfig.json",
5: "compilerOptions": {
6: "outDir": "./out-tsc/app",
7: "types": [],
8: "moduleResolution": "bundler"
9: },
10: "files": [
11: "src/angular-main.ts"
12: ],
13: "include": [
14: "src/angular-main.ts", // Your Angular entry point, or whatever it's called
15: "src/app/**/*.ts",
16: "src/**/*.d.ts"
17: ],
18: "exclude": [ // Exclude electron main file and environment files specific to electron if any
19: "src/electron-main.ts",
20: "src/environments/*.electron.ts",
21: "src/**/*.spec.ts" // Exclude tests (tests are configured separately as in my previous responses)
22: ]
23: }
24:
and check how compiler work :
# tsc --traceResolution -p tsconfig.app.json
(5) And finally check how all Angular now working with another TSC-compiler options and another entry point.
# ng serve
4. Add Electron features.
Now we need to Add 3 new files:
- tsconfig.electron.json
- src\electron-main.ts
- src\preload.js
(1) Also we need to change package.json, and commands related to electron. Package cross-env what provided environment variables will installed automatically on first start.
1: {
2: "main": "./out-tsc/electron-main/electron-main.js",
3: "name": "angular-electron",
4: "version": "0.0.0",
5: "scripts": {
6: "build:electron-main": "tsc -p tsconfig.electron.json",
7: "electron:start": "npm run build:electron-main && npx cross-env NODE_ENV=development electron .",
8: "electron:build": "electron .",
9: "ng": "ng",
10: "start": "ng serve",
11: "build": "ng build",
12: "watch": "ng build --watch --configuration development",
13: "test": "ng test"
14: },
15: ...
(2) tsconfig.electron.json:
1: {
2: "extends": "./tsconfig.json", // Inherit from base config
3: "compilerOptions": {
4: "module": "CommonJS", // For Node.js compatibility. Or System if using outFile
5: "outDir": "./out-tsc/electron-main" // If bundling with outFile, otherwise leave this out
6: },
7:
8: // Don't include Angular files here
9: "include": [
10: "src/electron-main.ts" // only include electron file and no Angular files
11: ],
12: "exclude": ["src/angular-main.ts", "src/**/*.spec.ts", "src/app/**/*.ts"]
13: }
(3) src\preload.js
1: const { contextBridge, ipcRenderer } = require('electron');
2:
3: contextBridge.exposeInMainWorld('electronAPI',{
4:
5: })
(4) standard Electron boorstraper src\electron-main.ts you can download from my repository https://github.com/Alex1998100/AngularElectron or there (if Microsoft, as usually, will ban me):
1: import { app, BrowserWindow } from 'electron';
2: import * as path from 'path';
3:
4: let mainWindow: BrowserWindow | null = null;
5:
6: const createWindow = () => {
7: mainWindow = new BrowserWindow({
8: width: 800,
9: height: 600,
10: webPreferences: {
11: preload: path.join(__dirname, 'preload.js'), // Add this if using a preload script
12: },
13: });
14:
15: mainWindow?.loadFile(
16: path.join(__dirname, '../dist/AngularElectron/index.html')
17: );
18: // Or loadURL if serving in development mode:
19: // mainWindow?.loadURL('http://localhost:4200'); // if Angular is served on this port
20:
21: mainWindow?.on('ready-to-show', () => {
22: // Prevents flicker. Only show when ready
23: mainWindow?.show(); // Show the window
24: if (process.env['NODE_ENV'] === 'development') {
25: mainWindow?.webContents.openDevTools();
26: }
27: });
28:
29: mainWindow.on('closed', () => {
30: mainWindow = null;
31: });
32: };
33:
34: app.whenReady().then(() => {
35: createWindow();
36:
37: app.on('activate', () => {
38: if (BrowserWindow.getAllWindows().length === 0) createWindow();
39: });
40:
41: // Quit when all windows are closed, except on macOS. There, it's common
42: // for applications and their menu bar to stay active until the user quits
43: // explicitly with Cmd + Q.
44: app.on('window-all-closed', () => {
45: if (process.platform !== 'darwin') {
46: app.quit();
47: }
48: });
49: });
5. Start project.
Angular can start as usually:
# ng serve
Electron can started:
# ng build # npm run electron:start
6. Key features to programming Electron application.
|