26.08.2024 г.
Electron, TypeScript и Parcel
Документацията на Electron е изцяло за JavaScript, но това не пречи да си използвате TypeScript, с който да генерира този JavaScript. Трябва да се спазват няколко простички правила, и то основно в пътищата на зареждане на файловете. Подготвил съм и малко допълнение за front-end частта. Вместо стандартната за Electron HTML страница ще направя малка компилация с Parcel.
Проекта
Най-напред ще си организираме проекта. В него ще има 2 подпапки - едната за Electron частта, др. за Browser частта. Създаваме папка electron-typescript-parcel
и я отваряме във VSCode - или който редактор ползвате. Отваряме вградения във VSCode терминал (или друг ако не ползвате VSCode) и изпълнявате:
npm init -y
Това ще създаде package.json
файл в папката electron-typescript-parcel
. Отваряте файла и редактирате полето author
. Като начало е достатъчно. Следва да добавим Electron модула в проекта.
npm install --save-dev electron
Ако ще ползвате GIT, сега е добре да изпълните:
git init
и да добавите .gitignore
файл. В него добавете като начало добавяме node_modules
.
След това добавяме 2 папки - electron
и browser
в папката на проекта. Както подсказват имената - в първата ще живее Electron, а във втората - front-end частта за браузъра.
Electron
През терминала влизаме в папката electron
и изпълняваме:
npm init -y
и веднага след това добавяме и TypeScript модула:
npm install --save-dev typescript
Зареждаме package.json
. В script частта добавяме "build": "tsc"
и махаме "main"
атрибута.
// electron/package.json
{
"name": "electron",
"version": "1.0.0",
"scripts": {
"build": "tsc"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"typescript": "^5.5.4"
}
}
В конзолата изпълняваме:
npx tsc --init
Това ще създаде tsconfig.json
файл. В него ще трябва да намерите "outDir"
, да премахнете коментираната час на реда и задавате "outDir": "../dist"
.
От тук следваме стандартните за Electron стъпки за създаване на базово приложение, като изпускаме частта за създаване на index.html
файла и renderer.js
файла, които ще добавим чрез Parcel.
Добавяме main.ts
файл в папката electron
и в него пишем:
// 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();
});
Това е примера от Electron документацията, който сменя тъмна или светла темата на приложението.
След това добавяме preload.ts
файл в папката electron
и в него пишем:
// electron/preload.ts
import { contextBridge, ipcRenderer } from "electron/renderer";
contextBridge.exposeInMainWorld("electronAPI", {
toggle: () => ipcRenderer.invoke("dark-mode:toggle"),
});
Browser
През терминала влизаме в папката browser
и изпълняваме:
npm init -y
след което инсталираме Parcel:
npm install --save-dev parcel
Зареждаме package.json
. В script частта добавяме "build": "parcel build index.html --dist-dir ../dist --no-source-maps --public-url ./ --no-optimize"
и махаме "main"
атрибута.
Създаваме index.html
файл в папката browser
и в него пишем:
<!-- 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>
Създаваме styles.css
файл в папката browser
и в него пишем:
/* browser/styles.css */
@media (prefers-color-scheme: dark) {
body { background: #333; color: white; }
}
@media (prefers-color-scheme: light) {
body { background: #ddd; color: black; }
}
Добавяме render.ts
файл в папката browser
и в него пишем:
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`;
});
}
За да 'компилираме' typescript файла с Parcel ще добавим в папката .parcelrc
файл и в него ще напишем:
// browser/.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"*.ts": ["@parcel/transformer-typescript-tsc"]
}
}
Старт
Връщаме се обратно в папката на проекта и редактираме в package.json
файла полетата scripts и main :
// package.json
{
"main": "./dist/main.js",
"scripts": {
"start": "npm run build --prefix ./electron && npm run build --prefix ./browser && electron ."
}
}
В .gitignore
файла добавяме dist
и .parcel-cache
папките и в командния ред изпълняваме:
npm start
След старта на приложението, ще се появи папка dist
в папката на проекта и в нея ще е целия код на Electron приложението.
Направил съм репозитори за този проект в GitHub.
Ако имате мнение или въпроси за статията, не се колебайте да ги споделите.