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.
Ако имате мнение или въпроси за статията, не се колебайте да ги споделите.
Логване на информация с Web Workers от Vue 3 към сървъра
Web Workers са малки, но мощни скриптове, които работят на 'заден план' в браузъра. И понеже не пречат на рендирането на приложението Ви, може да ги товарите с разни задачи, които да изпълняват.
Vue Router и Main файла
При стартиране на нов Vue проект, използвам Quick Start секцията на сайта на Vue. След това, задължително, правя няколко малки промени, преди да добавя проекта към Source Control банката.