Last Updated:
Electron Quick Start with TypeScript
Electron is an open-source framework developed by GitHub that allows you to build cross-platform desktop applications using web technologies such as HTML, CSS, and JavaScript. TypeScript, on the other hand, is a superset of JavaScript that adds static typing to the language, making it more robust and maintainable, especially for larger projects. Combining Electron with TypeScript can significantly enhance the development experience and the quality of your desktop applications. This blog post will guide you through a quick start with Electron using TypeScript, covering fundamental concepts, usage methods, common practices, and best practices.
Table of Contents#
- Fundamental Concepts
- Setting up the Project
- Usage Methods
- Common Practices
- Best Practices
- Conclusion
- References
Fundamental Concepts#
Electron Basics#
- Main Process: The main process in an Electron application is responsible for creating and managing browser windows. It runs a single instance of Node.js and can use all Node.js APIs.
- Renderer Process: Each browser window in an Electron application runs in its own renderer process. The renderer process is similar to a traditional web page and can access web APIs like the DOM.
- Inter-Process Communication (IPC): Since the main process and renderer processes are separate, Electron provides mechanisms for them to communicate with each other, such as
ipcMainin the main process andipcRendererin the renderer process.
TypeScript Basics#
- Static Typing: TypeScript allows you to define types for variables, functions, and objects. This helps catch type-related errors at compile-time rather than at runtime.
- Interfaces and Classes: You can use interfaces to define the shape of objects and classes to create reusable object-oriented code.
- Transpilation: TypeScript code needs to be transpiled into JavaScript before it can be run in the browser or Node.js. Tools like
tsc(TypeScript compiler) are used for this purpose.
Setting up the Project#
Step 1: Initialize a new project#
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 -yStep 2: Install dependencies#
Install Electron and TypeScript as development dependencies.
npm install electron typescript --save - devStep 3: Configure TypeScript#
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
}
}Step 4: Create project structure#
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>Usage Methods#
Main Process (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 Process (renderer.ts)#
// You can use web APIs here
const heading = document.querySelector('h1');
if (heading) {
heading.textContent = 'Updated heading from TypeScript!';
}Transpile and Run#
Transpile the TypeScript code using the TypeScript compiler:
npx tscRun the Electron application:
npx electron.Common Practices#
Error Handling#
- Main Process: In the main process, use
try - catchblocks 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);
}
}- Renderer Process: Use
try - catchblocks 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);
}IPC Communication#
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);
});Best Practices#
Code Organization#
- Separate Concerns: Keep the main process and renderer process code separate. Use modular design principles to break down your code into smaller, more manageable functions and classes.
- Use Interfaces: Define interfaces for data structures passed between the main and renderer processes. This makes the code more self-documenting and easier to maintain.
Security#
- Context Isolation: Enable context isolation in the
webPreferencesof theBrowserWindowto 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')
}
});Performance#
- Lazy Loading: If your application has large components or data, consider using lazy loading techniques to improve startup performance.
Conclusion#
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.