Building a Desktop Application with Electron: A Step-by-Step Guide
This chapter will guide you through the process of creating a desktop application using Electron, a powerful framework for building cross-platform applications with web technologies. We will develop a simple image resizing application to illustrate key Electron concepts and functionalities. This project serves as an excellent starting point for understanding Electron and building more complex desktop applications.
1. Introduction to Electron
Electron is a versatile framework that allows developers to build desktop applications for Windows, macOS, and Linux using web technologies such as HTML, CSS, and JavaScript. This means you can leverage your existing web development skills to create native desktop applications. Many popular applications are built using Electron, demonstrating its capabilities and widespread adoption. Examples include:
- VS Code: A widely used source code editor.
- Atom: Another popular, customizable text editor.
- Postman: A tool for API development and testing.
- Slack: A popular communication platform for teams.
Electron: An open-source framework developed by GitHub for building cross-platform desktop applications with HTML, CSS, and JavaScript. It allows developers to use web technologies to create native-like applications that can run on Windows, macOS, and Linux.
Electron is a favorite technology for many developers due to its cross-platform nature and the accessibility of web development skills. This chapter will guide you through building a practical project to get hands-on experience with Electron.
2. Project Overview: Image Resizer Application
In this chapter, we will build an “Image Resizer” application. This application will allow users to:
- Select an image file from their computer.
- Specify desired width and height dimensions for the image.
- Resize the image and save the resized version to a designated output folder.
This application offers simple yet fundamental functionality, making it an ideal project for beginners to grasp the core concepts of Electron development. It will cover essential aspects such as:
- The main process and renderer process architecture in Electron.
- Creating application menus.
- Handling user input and events.
- Inter-process communication (IPC).
Main Process: In Electron, the main process acts as the application’s entry point and manages the application lifecycle. It is responsible for creating and managing browser windows (renderer processes), handling system events, and interacting with the operating system.
Renderer Process: Renderer processes are responsible for displaying the user interface of an Electron application. Each browser window in an Electron application runs in its own renderer process, which is essentially a Chromium instance rendering web content (HTML, CSS, and JavaScript).
3. Prerequisites
To follow along with this chapter, you will need:
- Basic JavaScript knowledge: A solid understanding of JavaScript is essential. Prior experience with Node.js is not strictly required for this project, although familiarity can be beneficial.
- Node.js and npm (Node Package Manager) installed: Electron applications are built using Node.js, and npm is used to manage project dependencies. Ensure you have Node.js and npm installed on your system. You can download them from the official Node.js website.
- A code editor: VS Code is recommended, but you can use any code editor of your choice.
It is recommended to set aside some dedicated time to focus on learning and building this application alongside the instructions provided.
4. Setting Up the Project
Let’s begin by setting up our project environment.
4.1. Creating the Project Folder
- Create a new, empty folder on your computer named
image-resizer-electron
. - Open this folder in your code editor (e.g., VS Code).
- Open the integrated terminal within your code editor.
4.2. Initializing package.json
We need to initialize a package.json
file, which is essential for Node.js projects to manage dependencies and project information.
- In the terminal, run the command:
npm init
- You will be prompted to answer a series of questions. For this project, you can use the following:
- package name:
image-resizer-electron
(or as desired) - version:
1.0.0
(or as desired) - description:
App to resize image dimensions
- entry point:
main.js
(Crucially, this file will be the entry point for the main process in Electron.) - author: Your Name (or as desired)
- license:
MIT
(or as desired)
- package name:
- Confirm the details by typing
yes
and pressing Enter.
This will generate a package.json
file in your project directory.
4.3. Adding Product Name
Open the package.json
file in your code editor. Add a productName
property to the JSON object. This name will be displayed in the application menu, especially on macOS.
{
"name": "image-resizer-electron",
"version": "1.0.0",
"description": "App to resize image dimensions",
"main": "main.js",
"author": "Your Name",
"license": "MIT",
"productName": "Image Resizer"
}
4.4. Installing Dependencies
We need to install the necessary packages for our Electron application.
-
In the terminal, run the following command to install Electron,
resize-img
(for image resizing functionality), andtoastify-js
(for user notifications):npm install electron resize-img toastify-js
- electron: The core Electron framework.
- resize-img: A Node.js package to handle image resizing.
- toastify-js: A JavaScript library to create toast notifications for user feedback.
After installation, you will find these packages listed under dependencies
in your package.json
file.
5. Structuring the Application: Main and Renderer Processes
Electron applications typically consist of two main processes: the main process and the renderer process.
- Main Process (main.js): This is the backend of your application. It manages the application lifecycle, creates windows, handles system events, and performs backend tasks like image resizing in our case.
- Renderer Process (renderer/index.html, renderer/renderer.js): This is the frontend of your application, responsible for the user interface. It displays web pages and interacts with the user.
5.1. Creating main.js
(Main Process)
-
Create a new file named
main.js
in the root of your project directory. -
For now, let’s add a simple
console.log
to verify it’s running:// main.js console.log("Hello from the main process!");
5.2. Modifying package.json
for the Start Script
We need to configure the start
script in package.json
to launch our Electron application.
-
Open
package.json
. -
Modify the
scripts
section to include astart
script that uses Electron to runmain.js
:"scripts": { "start": "electron ." },
This script will execute Electron, using the current directory (
.
) as the path to your application, which will runmain.js
by default as specified in themain
property.
5.3. Running the Application for the First Time
-
In the terminal, run the command:
npm start
This command executes the
start
script we just defined. You should see “Hello from the main process!” logged in your terminal. This confirms that Electron is running and executing yourmain.js
file as a Node.js process. To stop the running process, pressCtrl+C
(orCmd+C
on macOS) in the terminal.
6. Creating the Main Window
Now let’s create the main application window, which will be the user interface of our Image Resizer.
6.1. Importing Modules in main.js
-
Open
main.js
. -
Import the
app
andBrowserWindow
modules from Electron. We also need thepath
module for handling file paths.// main.js const { app, BrowserWindow } = require('electron'); const path = require('path');
require(): In Node.js and Electron’s main process,
require()
is a function used to import modules. It allows you to load and use external libraries, built-in modules, or other JavaScript files within your application.
6.2. Creating the createMainWindow
Function
Create a function named createMainWindow
that will handle the creation of the main application window.
// main.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow; // Declare mainWindow in the global scope
function createMainWindow() {
mainWindow = new BrowserWindow({
title: 'Image Resizer',
width: 500,
height: 600,
});
mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html'));
}
new BrowserWindow(options)
: This creates a new application window. Theoptions
object allows you to configure various window properties like title, width, height, etc.mainWindow.loadFile(filePath)
: This method loads an HTML file into the browser window.path.join(__dirname, 'renderer', 'index.html')
constructs the absolute path to yourindex.html
file located in therenderer
folder.__dirname
refers to the directory wheremain.js
is located.
6.3. Creating renderer/index.html
(Renderer Process UI)
-
Create a new folder named
renderer
in the root of your project directory. -
Inside the
renderer
folder, create a new file namedindex.html
. -
Add basic HTML boilerplate code to
index.html
:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Image Resizer</title> </head> <body> <h1>Hello World from Renderer Process!</h1> </body> </html>
6.4. Calling createMainWindow
when the App is Ready
We need to call createMainWindow
function when Electron is ready to launch the application.
-
In
main.js
, add the following code to callcreateMainWindow
when theapp
emits theready
event:// main.js const { app, BrowserWindow } = require('electron'); const path = require('path'); let mainWindow; function createMainWindow() { mainWindow = new BrowserWindow({ title: 'Image Resizer', width: 500, height: 600, }); mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html')); } app.whenReady().then(createMainWindow);
app.whenReady().then(callback)
: This ensures thatcreateMainWindow
is executed only after Electron has fully initialized and is ready to create windows.
6.5. Running the Application with the Main Window
-
Run
npm start
in the terminal.You should now see a desktop window titled “Image Resizer” displaying “Hello World from Renderer Process!“. This confirms that your main window is successfully created and loading the
index.html
file.
7. Boilerplate Code for Application Lifecycle
Electron applications require some standard boilerplate code to handle application lifecycle events correctly, especially across different operating systems (Windows, macOS).
7.1. Handling Window Closure (macOS vs. Windows/Linux)
macOS handles window closing differently than Windows and Linux. On macOS, closing all windows typically does not quit the application; it remains running in the background. On Windows and Linux, closing the last window usually quits the application. We need to replicate these platform-specific behaviors.
-
In
main.js
, add the following event listeners to theapp
object:// main.js const { app, BrowserWindow } = require('electron'); const path = require('path'); let mainWindow; const isMac = process.platform === 'darwin'; // Check if platform is macOS function createMainWindow() { // ... (rest of createMainWindow function) } app.whenReady().then(createMainWindow); app.on('window-all-closed', () => { if (!isMac) { // Quit app only if not on macOS app.quit(); } }); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createMainWindow(); // Re-create main window if none exist when activated (macOS dock icon click) } });
process.platform === 'darwin'
: This checks if the operating system is macOS (Darwin kernel).app.on('window-all-closed', callback)
: This event is emitted when all application windows are closed.app.quit()
: This method quits the entire Electron application.app.on('activate', callback)
: On macOS, this event is emitted when the application is activated, often by clicking the dock icon. We check if any windows are open and, if not, re-create the main window.
7.2. Declaring isMac
Variable
To simplify platform checks throughout the code, let’s declare a variable isMac
at the top of main.js
:
// main.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
const isMac = process.platform === 'darwin'; // Variable to check if platform is macOS
let mainWindow;
// ... (rest of main.js code)
8. Development Enhancements: DevTools and Live Reloading
For a smoother development experience, we can enable DevTools to debug our renderer process and use a tool for live reloading to automatically restart the application on code changes.
8.1. Opening DevTools in Development Mode
Chromium DevTools is a powerful debugging tool for web technologies. We can automatically open DevTools when the application starts in development mode.
-
In
main.js
, add the following code inside thecreateMainWindow
function, after loading the file:// main.js function createMainWindow() { mainWindow = new BrowserWindow({ title: 'Image Resizer', width: 500, height: 600, }); mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html')); // Open DevTools if in development mode if (process.env.NODE_ENV !== 'production') { mainWindow.webContents.openDevTools(); } }
process.env.NODE_ENV !== 'production'
: This checks if theNODE_ENV
environment variable is not set to ‘production’. By default, when you runnpm start
,NODE_ENV
is typically not set, effectively putting you in development mode.mainWindow.webContents.openDevTools()
: This method opens the DevTools panel for the associated browser window.
-
Modify the
width
of theBrowserWindow
to be wider in development mode to accommodate DevTools:// main.js function createMainWindow() { mainWindow = new BrowserWindow({ title: 'Image Resizer', width: process.env.NODE_ENV !== 'production' ? 1000 : 500, // Wider window in dev mode height: 600, }); // ... (rest of createMainWindow function) }
This uses a ternary operator to set the window width to 1000 pixels in development mode and 500 pixels in production mode.
8.2. Using electronmon
for Live Reloading
Restarting the application manually every time you make a code change can be tedious. electronmon
is a helpful tool that automatically restarts your Electron application whenever changes are detected in your code.
-
Install
electronmon
globally (or locally as a dev dependency if preferred):npm install -g electronmon
-
Modify the
start
script inpackage.json
to useelectronmon
instead ofelectron
:"scripts": { "start": "electronmon ." },
-
Run
npm start
.Now, when you make changes to
main.js
or files in therenderer
folder,electronmon
will automatically restart your Electron application, providing a faster development workflow.
electronmon: A development utility that automatically restarts your Electron application when code changes are detected. It streamlines the development process by eliminating the need to manually restart the application after each modification.
9. Implementing the User Interface (UI)
Let’s integrate the provided UI theme files to visually enhance our Image Resizer application.
9.1. Obtaining Theme Files
- Download or clone the provided GitHub repository for theme files.
- Locate the
theme_files
folder within the repository. - Copy the contents of the
theme_files
folder (index.html
,about.html
,css
,img
,js
) into yourrenderer
folder, replacing the existingindex.html
file.
9.2. Renaming script.js
to renderer.js
For clarity and to better represent its role as the renderer process’s JavaScript file, rename script.js
to renderer.js
within the renderer/js
folder. Remember to update the script tag in index.html
to reflect this change:
<!-- index.html -->
<script src="./js/renderer.js"></script>
9.3. Clearing renderer.js
For this chapter, we will write the renderer process JavaScript from scratch. Open renderer/js/renderer.js
and clear any existing content, leaving it as an empty file.
9.4. Addressing Content Security Policy (CSP) Warning
When running the application with the new UI, you might see a warning message in the DevTools console related to Content Security Policy (CSP). This is a security feature of Chromium. To resolve this for development purposes, we can add a <meta>
tag to both index.html
and about.html
files.
-
Open
renderer/index.html
andrenderer/about.html
. -
Add the following
<meta>
tag within the<head>
section of both files:<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
Content Security Policy (CSP): A security standard for web browsers that helps prevent cross-site scripting (XSS) attacks. It allows you to define a policy that controls the sources from which the browser is allowed to load resources such as scripts, stylesheets, and images.
This meta tag relaxes the CSP for scripts, allowing scripts from the same origin ('self'
) to be executed. In a production application, a more restrictive CSP should be implemented for enhanced security.
After these steps, running npm start
should display the themed UI for the Image Resizer application.
10. Customizing the Application Menu
Electron allows you to customize the default application menu, which appears at the top of the application window (on Windows and Linux) or at the top of the screen (on macOS). We will create a custom menu with “File” and “Help” menus.
10.1. Creating a Menu Template in main.js
-
In
main.js
, import theMenu
module from Electron:// main.js const { app, BrowserWindow, Menu } = require('electron'); // Import Menu // ... (rest of main.js code)
-
Below the
createMainWindow
function, create amenuTemplate
array. This array will define the structure of our menu.// main.js const { app, BrowserWindow, Menu } = require('electron'); const path = require('path'); // ... (isMac and mainWindow variables, createMainWindow function, app event listeners) const menuTemplate = [ { label: 'File', // File menu submenu: [ { label: 'Quit', // Quit menu item accelerator: isMac ? 'Command+W' : 'Ctrl+W', // Shortcut for quit click: () => { app.quit(); // Quit application on click }, }, ], }, ];
Menu
module: Provides functionality to create native application menus.menuTemplate
: An array of menu items that defines the structure of the application menu. Each object in the array represents a top-level menu item (like “File”).label
: The text displayed for the menu item.submenu
: An array of submenu items that appear when a top-level menu item is clicked or hovered.accelerator
: Defines a keyboard shortcut for the menu item.isMac ? 'Command+W' : 'Ctrl+W'
sets different shortcuts for macOS (Command+W) and Windows/Linux (Ctrl+W).click
: A function that is executed when the menu item is clicked.app.quit()
terminates the application.
10.2. Implementing the Menu
-
In
main.js
, inside theapp.whenReady().then()
block, after callingcreateMainWindow()
, add the following code to build and set the application menu:// main.js app.whenReady().then(() => { createMainWindow(); // Implement Menu const mainMenu = Menu.buildFromTemplate(menuTemplate); // Build menu from template Menu.setApplicationMenu(mainMenu); // Set the application menu });
Menu.buildFromTemplate(template)
: Creates aMenu
object from the providedmenuTemplate
.Menu.setApplicationMenu(menu)
: Sets the application menu for the entire application.
-
Run
npm start
. You should now see a “File” menu in your application’s menu bar with a “Quit” option.
10.3. Using Menu Roles
Electron provides pre-defined “roles” for common menu items like “File,” “Edit,” and “View.” Using roles can simplify menu creation and ensure platform-consistent behavior. Let’s modify the “File” menu to use the fileMenu
role.
-
Modify the
menuTemplate
inmain.js
as follows:// main.js const menuTemplate = [ { role: 'fileMenu', // Use 'fileMenu' role for File menu }, ];
role: 'fileMenu'
: This replaces the manual “File” menu definition with Electron’s built-in “fileMenu” role, which provides standard file-related menu items like “Close Window” (instead of “Quit” in this simplified example).
-
Run
npm start
. The “File” menu will now display items appropriate for the platform, such as “Close Window” on macOS.
10.4. Adding Platform-Specific Menu Items (About Menu)
On macOS, it’s customary to have an “About” menu item under the application name menu. On Windows and Linux, “About” is typically placed under a “Help” menu. We need to create platform-specific menu structures to accommodate this.
-
Modify the
menuTemplate
inmain.js
to include platform-specific “About” menus:// main.js const menuTemplate = [ ...(isMac ? [ { label: app.name, // Application name menu on macOS submenu: [{ role: 'about' }], // About item under app name menu }, ] : []), // Empty array if not macOS { role: 'fileMenu', }, ...(isMac ? [] : [ { label: 'Help', // Help menu on Windows/Linux submenu: [{ role: 'about' }], // About item under Help menu }, ]), // Empty array if macOS ];
...(isMac ? [...] : [])
: This uses the spread syntax (...
) and a ternary operator to conditionally include menu items based on theisMac
variable.app.name
: Electron providesapp.name
to get the application name, which is useful for the macOS application menu.role: 'about'
: Electron’s built-in ‘about’ role provides a standard “About” dialog.
-
Run
npm start
. On macOS, you should see an application name menu with an “About” item. On Windows/Linux, you should see a “Help” menu with an “About” item.
10.5. Creating a Custom “About” Window
Instead of using the default “About” dialog provided by the 'about'
role, let’s create a custom “About” window that displays our own content from renderer/about.html
.
-
Create a new function
createAboutWindow
inmain.js
:// main.js let aboutWindow; // Declare aboutWindow in global scope function createAboutWindow() { aboutWindow = new BrowserWindow({ title: 'About Image Resizer', width: 300, height: 300, resizable: false, // Prevent window resizing parent: mainWindow, // Make aboutWindow a child of mainWindow modal: true, // Make aboutWindow modal (blocks interaction with mainWindow) }); aboutWindow.loadFile(path.join(__dirname, 'renderer', 'about.html')); }
resizable: false
: Disables window resizing for the “About” window.parent: mainWindow
: MakesaboutWindow
a child window ofmainWindow
.modal: true
: MakesaboutWindow
modal, meaning the user must interact with it before interacting with the main window.
-
Modify the
menuTemplate
to usecreateAboutWindow
for the “About” menu items instead of the'about'
role:// main.js const menuTemplate = [ ...(isMac ? [ { label: app.name, submenu: [ { label: 'About', // Custom About menu item click: createAboutWindow, // Call createAboutWindow on click }, ], }, ] : []), { role: 'fileMenu', }, ...(isMac ? [] : [ { label: 'Help', submenu: [ { label: 'About', // Custom About menu item click: createAboutWindow, // Call createAboutWindow on click }, ], }, ]), ];
click: createAboutWindow
: Sets theclick
handler for the “About” menu items to call thecreateAboutWindow
function.
-
Run
npm start
. Now, clicking the “About” menu item (under the application name on macOS or under “Help” on Windows/Linux) should open a custom “About” window displaying the content fromrenderer/about.html
.
11. Handling User Input and Image Selection (Renderer Process)
Now let’s start implementing the core functionality of the Image Resizer application by handling user input in the renderer process.
11.1. Selecting UI Elements in renderer.js
-
Create a new file
renderer.js
in therenderer/js
folder (if it doesn’t already exist). -
Open
renderer/js/renderer.js
. -
Select the necessary UI elements using their IDs from
index.html
. Add the following JavaScript code torenderer.js
:// renderer/js/renderer.js const form = document.getElementById('img-form'); const img = document.getElementById('img'); const outputPath = document.getElementById('output-path'); const filename = document.getElementById('filename'); const heightInput = document.getElementById('height'); const widthInput = document.getElementById('width');
This code uses
document.getElementById()
to retrieve references to the HTML elements we’ll be interacting with, such as the form, image input, output path display, filename display, and width/height input fields.
11.2. Adding Event Listener for Image Input Change
We need to add an event listener to the image input (img
) to detect when the user selects an image file.
-
In
renderer/js/renderer.js
, add the following event listener code:// renderer/js/renderer.js const form = document.getElementById('img-form'); const img = document.getElementById('img'); const outputPath = document.getElementById('output-path'); const filename = document.getElementById('filename'); const heightInput = document.getElementById('height'); const widthInput = document.getElementById('width'); img.addEventListener('change', loadImage); // Event listener for image input change
This line adds an event listener to the
img
element that listens for the ‘change’ event. When the user selects a file in the image input, theloadImage
function will be executed.
11.3. Implementing loadImage
Function
Now, let’s implement the loadImage
function to handle the image selection process.
-
In
renderer/js/renderer.js
, add theloadImage
function:// renderer/js/renderer.js const form = document.getElementById('img-form'); const img = document.getElementById('img'); const outputPath = document.getElementById('output-path'); const filename = document.getElementById('filename'); const heightInput = document.getElementById('height'); const widthInput = document.getElementById('width'); img.addEventListener('change', loadImage); function loadImage(e) { const file = e.target.files[0]; // Get selected file if (!file) { return; // No file selected, exit function } // Check if file is an image if (!isFileImage(file)) { alertError('Please select an image'); // Alert error if not an image return; } // Display form and filename form.style.display = 'block'; // Show the form filename.innerText = file.name; // Display filename // Get original dimensions and set input values const image = new Image(); image.src = URL.createObjectURL(file); // Create object URL for image image.onload = function () { widthInput.value = this.width; // Set width input value to original width heightInput.value = this.height; // Set height input value to original height }; }
e.target.files[0]
: Gets the first file from thefiles
array of the input element. Even if it’s a single file input, the files are still stored in an array.isFileImage(file)
: A function (to be defined later) to check if the selected file is a valid image type.alertError('Please select an image')
: A function (to be defined later) to display an error message to the user.form.style.display = 'block'
: Makes the image resizing form visible. Initially, it’s hidden using CSS classhidden
.filename.innerText = file.name
: Displays the selected image filename in thefilename
span.new Image()
: Creates a newImage
object in JavaScript.URL.createObjectURL(file)
: Creates a temporary URL that represents the selected image file in memory. This URL can be used as thesrc
of anImage
object.image.onload = function() { ... }
: An event handler that is executed when the image has fully loaded. Inside this handler, we set thevalue
of thewidthInput
andheightInput
fields to thewidth
andheight
of the loaded image usingthis.width
andthis.height
.
11.4. Implementing isFileImage
Function
We need to implement the isFileImage
function to verify that the selected file is indeed an image (GIF, PNG, or JPEG).
-
In
renderer/js/renderer.js
, add theisFileImage
function:// renderer/js/renderer.js // ... (UI element selections, event listener, loadImage function) function isFileImage(file) { const acceptedImageTypes = ['image/gif', 'image/png', 'image/jpeg']; // Array of accepted image types return file && acceptedImageTypes.includes(file.type); // Check if file type is in accepted types }
acceptedImageTypes
: An array containing MIME types for GIF, PNG, and JPEG images.file && acceptedImageTypes.includes(file.type)
: Checks if afile
object exists and if itstype
property (MIME type) is included in theacceptedImageTypes
array.
11.5. Implementing alertError
Function (Using toastify-js
)
Let’s implement the alertError
function using the toastify-js
library to display user-friendly error messages.
-
Before we can use
toastify-js
in the renderer process, we need to expose it from the preload script. Create a filepreload.js
in the root directory of your project if you haven’t already. Add the following code topreload.js
:// preload.js const { contextBridge, ipcRenderer } = require('electron'); const os = require('os'); const path = require('path'); const toastify = require('toastify-js'); // Import toastify-js in preload contextBridge.exposeInMainWorld('os', { homedir: () => os.homedir(), }); contextBridge.exposeInMainWorld('path', { join: (...args) => path.join(...args), }); contextBridge.exposeInMainWorld('ipcRenderer', { send: (channel, data) => ipcRenderer.send(channel, data), on: (channel, func) => ipcRenderer.on(channel, func), }); contextBridge.exposeInMainWorld('toastify', { // Expose toastify to renderer toast: (options) => toastify(options).showToast(), });
const toastify = require('toastify-js');
: Imports thetoastify-js
module in the preload script, making it available to be exposed to the renderer process.contextBridge.exposeInMainWorld('toastify', { ... });
: Exposes an object namedtoastify
to the renderer process’swindow
object.toast: (options) => toastify(options).showToast()
: Exposes atoast
function that, when called from the renderer process, will display a toast notification usingtoastify-js
.
-
In
main.js
, make sure you have configured thepreload
script for yourBrowserWindow
:// main.js function createMainWindow() { mainWindow = new BrowserWindow({ title: 'Image Resizer', width: process.env.NODE_ENV !== 'production' ? 1000 : 500, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), // Set preload script contextIsolation: true, // Enable context isolation for security nodeIntegration: true, // Enable Node.js integration in renderer (use with caution) }, }); // ... (rest of createMainWindow function) }
webPreferences: { preload: path.join(__dirname, 'preload.js'), ... }
: Configures web preferences for theBrowserWindow
, specifically setting thepreload
script topreload.js
.contextIsolation: true
: Enables context isolation for security, separating the renderer process’s JavaScript context from the preload script’s context.nodeIntegration: true
: Enables Node.js integration in the renderer process, allowing you to use Node.js modules directly in the renderer (use with caution for security reasons; context isolation is recommended).
-
In
renderer/js/renderer.js
, implement thealertError
function using the exposedwindow.toastify.toast()
function:// renderer/js/renderer.js // ... (UI element selections, event listener, loadImage, isFileImage functions) function alertError(message) { window.toastify.toast({ // Use exposed toastify function from preload text: message, duration: 5000, // 5 seconds close: false, style: { background: 'red', color: 'white', textAlign: 'center', }, }); }
window.toastify.toast({ ... })
: Calls thetoast
function exposed through the preload script viacontextBridge
. This will display a red-colored toast notification with the provided errormessage
.
-
Also implement the
alertSuccess
function for success messages, similar toalertError
, but with a green background:// renderer/js/renderer.js // ... (UI element selections, event listener, loadImage, isFileImage, alertError functions) function alertSuccess(message) { window.toastify.toast({ // Use exposed toastify function from preload text: message, duration: 5000, // 5 seconds close: false, style: { background: 'green', color: 'white', textAlign: 'center', }, }); }
Now, when you run the application and try to select a non-image file, you should see a red toast notification displayed at the bottom of the window with the message “Please select an image.”
This comprehensive educational text provides a structured and detailed guide for building an Electron application. It breaks down the process into manageable steps, explains key concepts, and includes definitions of technical terms to enhance understanding for educational purposes. This text can serve as a valuable resource for anyone learning Electron development.