Skip to content

howbizarre/electron-typescript-parcel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Electron, TypeScript & Parcel

TL;DR

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.

Step by Step the Project

Introduction

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.

The Project

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.

Electron

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"),
});

Browser

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"]
  }
}

Start

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.

License

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/