Download the project and need do execute npm install
in the root
project folder, then in electron
and browser
folders.
After that, execute npm start
in the root
project folder.
Documentation for Electron is entirely in JavaScript, but that doesn't stop you from using TypeScript to generate that JavaScript. A few simple rules must be followed, mainly in the file loading paths. I have also prepared a small addition for the front-end part. Instead of the standard Electron HTML page, I will make a small compilation with Parcel.
First, we will organize our project. It will have 2 subfolders - one for the Electron part, the other for the Browser part. We create a folder electron-typescript-parcel
and open it in VSCode - or whichever editor you use. Open the built-in terminal in VSCode (or another if you don't use VSCode) and execute:
npm init -y
This will create a package.json
file in the electron-typescript-parcel
folder. Open the file and edit the author
field. As a start, it is enough. Next, we need to add the Electron module to the project.
npm install --save-dev electron
If you are going to use GIT, now is a good time to execute:
git init
and add a .gitignore
file. Add node_modules
as a start.
Then add 2 folders - electron
and browser
in the project folder. As the names suggest - Electron will live in the first, and the front-end part for the browser will live in the second.
Through the terminal, enter the electron
folder and execute:
npm init -y
and immediately after that add the TypeScript module:
npm install --save-dev typescript
Load package.json
. In the script part, add "build": "tsc"
and remove the "main"
attribute.
// electron/package.json
{
"name": "electron",
"version": "1.0.0",
"scripts": {
"build": "tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"typescript": "^5.5.4"
}
}
In the console execute:
npx tsc --init
This will create a tsconfig.json
file. In it, you will need to find "outDir"
, uncomment the line, and set "outDir": "../dist"
.
From here, we follow the standard steps for creating a basic Electron application, skipping the part about creating the index.html
file and renderer.js
file, which we will add through Parcel.
Add a main.ts
file to the electron
folder and write the following code:
// electron/main.ts
import { app, BrowserWindow, ipcMain, nativeTheme } from "electron";
import path from "node:path";
/**
* Creates a new window and loads an HTML file.
*/
const createWindow = (): void => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, "./preload.js"),
},
});
mainWindow.loadFile("./dist/index.html");
ipcMain.handle("dark-mode:toggle", () => {
if (nativeTheme.shouldUseDarkColors) {
nativeTheme.themeSource = "light";
} else {
nativeTheme.themeSource = "dark";
}
return nativeTheme.shouldUseDarkColors;
});
};
app.whenReady().then(() => {
createWindow();
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});
This is an example from the Electron documentation that changes the dark or light theme of the application.
Next, we add a preload.ts
file to the electron
folder and write the following code:
// electron/preload.ts
import { contextBridge, ipcRenderer } from "electron/renderer";
contextBridge.exposeInMainWorld("electronAPI", {
toggle: () => ipcRenderer.invoke("dark-mode:toggle"),
});
Through the terminal, we navigate to the browser
folder and execute:
npm init -y
After that, we install Parcel:
npm install --save-dev parcel
Loading package.json
. In the script section, we add "build": "parcel build index.html --dist-dir ../dist --no-source-maps --public-url ./ --no-optimize"
and remove the "main"
attribute.
Create an index.html
file in the browser
folder and write the following code:
<!-- browser/index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
<p>Current theme source: <strong id="theme-source">System</strong></p>
<p><button id="toggle-dark-mode">Toggle Theme Color</button></p>
<script src="./render.ts"></script>
</body>
</html>
Creating a styles.css
file in the browser
folder and writing the following code in it:
/* browser/styles.css */
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}
Adding a render.ts
file to the browser
folder and writing the following code in it:
const toggleDarkMode = document.getElementById("toggle-dark-mode");
const themeSource = document.getElementById("theme-source");
if (themeSource && toggleDarkMode) {
toggleDarkMode.addEventListener("click", async () => {
// @ts-expect-error
const isDarkMode = await window.electronAPI.toggle();
themeSource.innerHTML = isDarkMode ? "Dark" : "Light";
toggleDarkMode.innerHTML = `Toggle ${!isDarkMode ? "Dark" : "Light"} Mode`;
});
}
To 'compile' the TypeScript file with Parcel, we will add a .parcelrc
file in the folder and write the following:
// browser/.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.ts": ["@parcel/transformer-typescript-tsc"]
}
}
We go back to the project folder and edit the scripts and main fields in the package.json
file:
// package.json
{
"main": "./dist/main.js",
"scripts": {
"start": "npm run build --prefix ./electron && npm run build --prefix ./browser && electron ."
}
}
In the .gitignore
file, we add the dist
and .parcel-cache
folders, and in the command line, we execute:
npm start
After starting the application, a dist
folder will appear in the project folder, containing all the code of the Electron application.
Electron, TypeScript & Parcel © 2024 by How Bizarre is licensed under Creative Commons Attribution 4.0 International. To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/