-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
83118f3
commit 40dbffd
Showing
2 changed files
with
249 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
# 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**](https://code.visualstudio.com/) - or whichever editor you use. Open the built-in terminal in VSCode (or another if you don't use VSCode) and execute: | ||
|
||
```bash | ||
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. | ||
|
||
```bash | ||
npm install --save-dev electron | ||
``` | ||
|
||
If you are going to use **GIT**, now is a good time to execute: | ||
|
||
```bash | ||
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: | ||
|
||
```bash | ||
npm init -y | ||
``` | ||
|
||
and immediately after that add the TypeScript module: | ||
|
||
```bash | ||
npm install --save-dev typescript | ||
``` | ||
|
||
Load `package.json`. In the **script** part, add `"build": "tsc"` and remove the `"main"` attribute. | ||
|
||
```json | ||
// 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: | ||
|
||
```bash | ||
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: | ||
|
||
```typescript | ||
// 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](https://www.electronjs.org/docs/latest/tutorial/dark-mode) 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: | ||
|
||
```typescript | ||
// 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: | ||
|
||
```bash | ||
npm init -y | ||
``` | ||
|
||
After that, we install ***Parcel***: | ||
|
||
```bash | ||
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: | ||
|
||
```html | ||
<!-- 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: | ||
|
||
```css | ||
/* 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: | ||
|
||
```typescript | ||
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: | ||
|
||
```json | ||
// 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: | ||
|
||
```json | ||
// 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: | ||
|
||
```bash | ||
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/ |