ipcMain
in the main process and ipcRenderer
in the renderer process.tsc
(TypeScript compiler) are used for this purpose.Create a new directory for your project and initialize a new Node.js project using npm
.
mkdir electron - typescript - app
cd electron - typescript - app
npm init -y
Install Electron and TypeScript as development dependencies.
npm install electron typescript --save - dev
Create a tsconfig.json
file in the root of your project with the following configuration:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Create a src
directory in the root of your project. Inside the src
directory, create the following files:
main.ts
: This will be the entry point for the main process.renderer.ts
: This will be the entry point for the renderer process.index.html
: This is the HTML file that will be loaded in the browser window.Here is a basic index.html
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
<meta name="viewport" content="width=device - width, initial - scale=1.0">
<title>Electron TypeScript App</title>
</head>
<body>
<h1>Hello, Electron with TypeScript!</h1>
<script src="renderer.js"></script>
</body>
</html>
main.ts
)import { app, BrowserWindow } from 'electron';
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
win.loadFile('src/index.html');
}
app.whenReady().then(() => {
createWindow();
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on('window - all - closed', function () {
if (process.platform!== 'darwin') app.quit();
});
renderer.ts
)// You can use web APIs here
const heading = document.querySelector('h1');
if (heading) {
heading.textContent = 'Updated heading from TypeScript!';
}
Transpile the TypeScript code using the TypeScript compiler:
npx tsc
Run the Electron application:
npx electron.
try - catch
blocks when dealing with asynchronous operations like file reading or network requests.async function someAsyncOperation() {
try {
// Perform some asynchronous operation
} catch (error) {
console.error('Error in main process:', error);
}
}
try - catch
blocks around code that might throw errors, especially when interacting with the DOM.try {
const element = document.getElementById('non - existent - element');
element.textContent = 'This will throw an error if the element doesn\'t exist';
} catch (error) {
console.error('Error in renderer process:', error);
}
When communicating between the main process and the renderer process, use the ipcMain
and ipcRenderer
modules.
Main Process (main.ts
)
import { app, BrowserWindow, ipcMain } from 'electron';
ipcMain.on('message - from - renderer', (event, arg) => {
console.log('Received message from renderer:', arg);
event.sender.send('message - from - main', 'Message received in main process');
});
Renderer Process (renderer.ts
)
import { ipcRenderer } from 'electron';
ipcRenderer.send('message - from - renderer', 'Hello from renderer');
ipcRenderer.on('message - from - main', (event, arg) => {
console.log('Received message from main:', arg);
});
webPreferences
of the BrowserWindow
to prevent the renderer process from directly accessing Node.js APIs. This helps protect against potential security vulnerabilities.const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
Combining Electron with TypeScript provides a powerful and robust way to build cross - platform desktop applications. By following the fundamental concepts, usage methods, common practices, and best practices outlined in this blog post, you can create high - quality Electron applications with TypeScript. Remember to keep your code organized, handle errors properly, and prioritize security and performance.