Building Cross-Platform Desktop Apps with Electron, Vite, Vue 3, and Electron Builder

Gohilnancy
Simform Engineering
7 min readOct 30, 2023

An easy guide to crafting versatile desktop applications with Electron.

Today, the boundary between web and desktop applications is becoming increasingly blurred. With the emergence of technologies like Electron, Vite, and Vue 3, you can use the power of both web and desktop development to create feature-rich and visually appealing cross-platform desktop applications.

In this blog post, we will guide you through the process of building a desktop app using the dynamic combination of Electron, Vite, Vue 3, and Electron Builder. This will enable you to create, develop, and package desktop applications that run seamlessly on Windows, macOS, and Linux.

What You Need to Know

  • Electron: It’s an open-source framework that lets you create desktop applications using web technologies. Electron is based on Node.js and Chromium. Examples of applications built with Electron include the popular Atom editor, Visual Studio Code, WordPress for desktop, and Slack. Behind the scenes, Electron combines the Chromium engine with Node.js runtime to read and run your codebase as a standalone desktop program.
  • Vite: It’s a build tool and development server that accelerates the development process by leveraging ES modules. It aims to provide a faster and leaner development experience for modern web projects.
  • Vue 3: The latest version of Vue.js, Vue 3, is known for its simplicity and reactivity.
  • Electron Builder: Electron Builder is a robust tool that simplifies packaging and distributing Electron applications. It supports creating installer packages for various platforms, streamlining the deployment process.

📄 Table of content

  • Prerequisites
  • Pros of using Electron
  • Cons of using Electron
  • Setup Project
  • What is IPC?
  • Conclusion

Prerequisites

Before we get started, make sure you have the following installed on your machine:

Pros

The following are some of the advantages of using Electron:

  • Single codebase — With Electron, you’ll only need one codebase to create desktop applications for different operating systems.
  • Leverage web skills — If you have prior experience working with basic web stacks (HTML, CSS, and JavaScript), it is super easy to get started with Electron.
  • Big community — The Electron community is quite a big and active one, largely because the framework is being used and supported by top companies across the globe.

Cons

The following are some of the disadvantages of using Electron:

  • Higher resource consumption — Desktop applications written in Electron consume more CPU and RAM compared to apps written in other environments, such as Java FX, Objective C, and so on
  • Larger app size — As previously stated, Electron applications bundle the Chromium engine during the build process, which results in a big app size even for a simple application.

Setting Up the Project

Let’s create a new Electron.js project with Vue 3.

1. Installing Vite

We’ll start by installing Vite globally. Open your terminal and run the following command:

npm install -g create-vite

2. Creating a Vite Project

Now, let’s create a new Vite project. Navigate to your desired project directory in the terminal and execute the following command:

create-vite my-electron-vue-app

3. Installing Dependencies

Enter your project directory:

cd my-electron-vue-app

Install Electron and Electron Builder as dependencies:

npm install electron electron-builder --save-dev

4. Project Structure

In your project directory, you’ll find a structure like this:

  • src: This is where you'll create your Vue components.
  • public: Place your static assets here.

File Structure:

The file structure will remain identical to a Vue project generated by Vue CLI, except for the “main.js” file.

In this file, you can configure the default width and height of the window the application launches with, set the application title, and add an auto-update feature, among other things.

5. Vue Development Server

Start the Vite development server:

npm run dev

This will provide a local development server that you can access at http://localhost:3000.

6. Creating the Main Electron File

Now, let’s create the entry point for your Electron app. In the project root directory, create a file named main.js. This file will define the Electron application's main process:

const { app, BrowserWindow } = require('electron');
let mainWindow;app.whenReady().then(() => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
});
mainWindow.loadURL('http://localhost:3000');
});

This code initializes an Electron app and creates a window that loads your Vue application running on localhost:3000.

7. Vue Components

In the src directory, you can create your Vue components as you would in a standard Vue project.

8. Electron Integration

To access Electron APIs from your Vue components, you can use the window.require syntax. For example:

const { ipcRenderer } = window.require('electron');

Building and Packaging Your Electron App

With your Vue app and Electron setup in place, it’s time to build and package your Electron app for distribution.

1. Building the Vue App

Build your Vue app:

npm run build

This command generates a production-ready build of your Vue application in the dist directory.

2. Updating the Main Electron File

In the main.js file, update the line that loads your app to point to the built Vue app:

mainWindow.loadFile('dist/index.html');

3. Electron Builder Configuration

To configure Electron Builder, create a electron-builder.yml file in your project root. This file specifies the build targets and settings for your application. Here's a basic example:

targets:
- target: nsis
arch: x64

This configuration instructs Electron Builder to build an installer package for Windows (NSIS) targeting the x64 architecture.

4. Packaging Your App

Now, you’re ready to package your Electron app for distribution. Run the following command:

npx electron-builder

Electron Builder will package your app according to your configuration settings and generate installer packages for your target platforms.

The output would resemble the one shown below:

You can also close the Devtools if needed, as it comes by default.

On closing Devtools, it will look like this:

What is IPC?

In Electron.js, Inter-Process Communication (IPC) is a mechanism that allows different processes in your Electron application to communicate with each other. The primary use cases for IPC are communication between the main process and renderer processes (web pages) or between different renderer processes.

Image Credit: insujang

Sending Messages from Renderer Process to Main Process

To send a message from the renderer process (your web page) to the main process, you can use ipcRenderer.send():

const { ipcRenderer } = require('electron');
// Send a message to the main process

ipcRenderer.send('message-channel', 'Hello from renderer process!');

In the example above, we import ipcRenderer from the 'electron' module and use ipcRenderer.send() to send a message with the channel name 'message-channel' and a message payload.

Receiving Messages in the Main Process

In the main process, you need to listen for messages on the same channel using the ipcMain module. Typically, this is done in the main script (main.js) of your Electron application:

const { app, BrowserWindow, ipcMain } = require('electron');
let mainWindow;

app.whenReady().then(() => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
});

mainWindow.loadFile('index.html');

// Listen for messages from renderer process
ipcMain.on('message-channel', (event, message) => {
console.log('Received message in main process:', message);
});
});

Here, we use ipcMain.on() to listen for messages on the 'message-channel'. When a message is received, we log it to the console.

Sending Messages from the Main Process to the Renderer Process

To send a message from the main process to the renderer process, you can use webContents.send() on the BrowserWindow instance representing the renderer process:

const { ipcMain } = require('electron');
// Send a message to the renderer process
ipcMain.on('send-to-renderer', (event) => {
event.sender.send('message-channel', 'Hello from main process!');
});

In this example, when the main process receives a message on the ‘send-to-renderer’ channel, it sends a response message to the renderer process using event.sender.send().

Receiving Messages in the Renderer Process

In the renderer process, you can listen for messages sent from the main process using ipcRenderer.on():

const { ipcRenderer } = require('electron');
// Listen for messages from main process
ipcRenderer.on('message-channel', (event, message) => {
console.log('Received message in renderer process:', message);
});

Here, we use ipcRenderer.on() to listen for messages on the 'message-channel' in the renderer process. When a message is received, we log it to the console.

These are the basics of using ipcRenderer in Electron to enable communication between the renderer process (front-end) and the main process (back-end) of your Electron application. This mechanism is crucial for building interactive and responsive desktop applications using Electron.

Reference:

https://www.electronjs.org/docs/latest

Conclusion

Combining Electron, Vite, Vue 3, and Electron Builder empowers you to create cross-platform desktop applications with the ease and familiarity of web development. Whether you’re building productivity tools, creative applications, or utilities, this tech stack provides the versatility to bring your ideas to life on the desktop.

As you begin to develop desktop applications this way, explore the rich documentation of these technologies to harness their full potential. The world of cross-platform desktop development is at your fingertips, and your creativity is the only limit to what you can achieve. Start building amazing desktop apps today!

For more updates on the latest tools and technologies, follow the Simform Engineering blog.

Follow Us: Twitter | LinkedIn

--

--