vite-electron-builder
Secure boilerplate for Electron app based on Vite. TypeScript + Vue/React/Angular/Svelte/Vanilla
Top Related Projects
🥳 Really simple Electron + Vite + Vue boilerplate.
Clone to try a simple Electron app
A Foundation for Scalable Cross-Platform Apps
Easily Build Your Vue.js App For Desktop With Electron
Ultra-fast bootstrapping with Angular and Electron :speedboat:
:electron: A complete tool for building and publishing Electron applications
Quick Overview
Vite-electron-builder is a template for building Electron applications using Vite, Vue 3, and TypeScript. It provides a robust setup for creating cross-platform desktop applications with a modern web technology stack, offering hot reloading, efficient builds, and a well-structured project layout.
Pros
- Fast development experience with Vite's hot module replacement (HMR)
- Strong typing support with TypeScript integration
- Cross-platform compatibility for Windows, macOS, and Linux
- Automated builds and releases using GitHub Actions
Cons
- Steeper learning curve for developers new to Electron or Vue 3
- Limited customization options compared to building from scratch
- Potential overhead for simple applications that don't require all features
- Dependency on specific versions of tools and libraries
Getting Started
-
Clone the repository:
git clone https://github.com/cawa-93/vite-electron-builder.git my-app cd my-app
-
Install dependencies:
npm install
-
Start the development server:
npm run watch
-
To build for production:
npm run build
The application will now be running in development mode. You can edit the files in the packages
directory to start customizing your application. The main application logic is in packages/renderer/src/App.vue
for the frontend and packages/main/src/index.ts
for the main Electron process.
Competitor Comparisons
🥳 Really simple Electron + Vite + Vue boilerplate.
Pros of electron-vite-vue
- Simpler project structure with fewer configuration files
- More active development and frequent updates
- Better integration with Vue 3 and its ecosystem
Cons of electron-vite-vue
- Less comprehensive build and packaging setup
- Fewer pre-configured development tools and scripts
- Limited TypeScript support out of the box
Code Comparison
electron-vite-vue:
import { app, BrowserWindow } from 'electron'
import path from 'path'
const createWindow = () => {
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
vite-electron-builder:
import { app, BrowserWindow } from 'electron'
import { join } from 'path'
import { URL } from 'url'
async function createWindow() {
const browserWindow = new BrowserWindow({
webPreferences: {
preload: join(__dirname, '../../preload/dist/index.cjs'),
},
})
await browserWindow.loadURL(
import.meta.env.DEV && import.meta.env.VITE_DEV_SERVER_URL !== undefined
? import.meta.env.VITE_DEV_SERVER_URL
: new URL('../renderer/dist/index.html', 'file://' + __dirname).toString()
)
}
The code comparison shows that vite-electron-builder has a more complex setup with TypeScript support and additional configuration options, while electron-vite-vue offers a simpler, more straightforward approach to creating an Electron window.
Clone to try a simple Electron app
Pros of electron-quick-start
- Simple and straightforward setup for beginners
- Minimal boilerplate code, making it easier to understand the basics
- Official Electron example, ensuring compatibility and best practices
Cons of electron-quick-start
- Lacks modern build tools and optimizations
- No built-in support for TypeScript or other advanced features
- Limited scaffolding for larger, more complex applications
Code Comparison
electron-quick-start:
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
vite-electron-builder:
import { app, BrowserWindow } from 'electron'
import { join } from 'path'
import { URL } from 'url'
async function createWindow() {
const browserWindow = new BrowserWindow({
show: false,
webPreferences: {
preload: join(__dirname, '../../preload/dist/index.cjs'),
},
})
await browserWindow.loadURL(
import.meta.env.DEV && import.meta.env.VITE_DEV_SERVER_URL !== undefined
? import.meta.env.VITE_DEV_SERVER_URL
: new URL('../renderer/dist/index.html', 'file://' + __dirname).toString()
)
browserWindow.show()
}
app.whenReady().then(createWindow)
The vite-electron-builder example showcases more advanced features, including TypeScript support, environment-based loading, and a more structured approach to window creation.
A Foundation for Scalable Cross-Platform Apps
Pros of electron-react-boilerplate
- More established project with a larger community and longer history
- Includes TypeScript support out of the box
- Offers a more comprehensive set of development tools and scripts
Cons of electron-react-boilerplate
- Uses webpack for bundling, which can be slower compared to Vite
- Has a more complex project structure, potentially steeper learning curve
- Less frequent updates and releases compared to vite-electron-builder
Code Comparison
electron-react-boilerplate:
import { app, BrowserWindow, shell, ipcMain } from 'electron';
import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
vite-electron-builder:
import { app, BrowserWindow } from 'electron'
import { join } from 'path'
import { URL } from 'url'
const isSingleInstance = app.requestSingleInstanceLock()
const isDevelopment = import.meta.env.MODE === 'development'
Both projects provide a solid foundation for building Electron applications with React. electron-react-boilerplate offers a more comprehensive setup with additional tools and TypeScript support, making it suitable for larger projects. However, it may have a steeper learning curve due to its complexity.
vite-electron-builder, on the other hand, leverages Vite for faster development and simpler configuration. It's more lightweight and may be easier for beginners or smaller projects. The choice between the two depends on specific project requirements and developer preferences.
Easily Build Your Vue.js App For Desktop With Electron
Pros of vue-cli-plugin-electron-builder
- Integrates seamlessly with Vue CLI, providing a familiar development experience for Vue developers
- Offers a more mature and stable ecosystem, with longer development history and wider community adoption
- Provides extensive documentation and examples, making it easier for beginners to get started
Cons of vue-cli-plugin-electron-builder
- Relies on Vue CLI, which may be considered outdated compared to more modern build tools like Vite
- Generally slower build times compared to Vite-based solutions, especially for larger projects
- Less flexibility in customizing the build process outside of Vue CLI's constraints
Code Comparison
vue-cli-plugin-electron-builder:
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
// Configure electron-builder options here
}
}
}
}
vite-electron-builder:
import { defineConfig } from 'vite'
import electron from 'vite-plugin-electron'
export default defineConfig({
plugins: [
electron({
// Configure Electron options here
})
]
})
The code comparison shows the different configuration approaches. vue-cli-plugin-electron-builder uses Vue CLI's configuration file, while vite-electron-builder leverages Vite's plugin system for a more modular setup.
Ultra-fast bootstrapping with Angular and Electron :speedboat:
Pros of angular-electron
- Built with Angular, providing a robust framework for large-scale applications
- Includes Angular CLI for easier development and project management
- Offers a more opinionated structure, which can be beneficial for team projects
Cons of angular-electron
- Potentially heavier and slower build process compared to Vite-based solutions
- May have a steeper learning curve for developers not familiar with Angular
- Less flexibility in terms of choosing frontend frameworks or libraries
Code Comparison
vite-electron-builder:
import { app, BrowserWindow } from 'electron'
import { join } from 'path'
import { URL } from 'url'
const createWindow = () => {
const browserWindow = new BrowserWindow({
show: false,
webPreferences: {
preload: join(__dirname, '../../preload/dist/index.cjs'),
},
})
// ... (window setup continues)
}
angular-electron:
import { app, BrowserWindow, screen } from 'electron';
import * as path from 'path';
import * as fs from 'fs';
let win: BrowserWindow = null;
const args = process.argv.slice(1),
serve = args.some(val => val === '--serve');
function createWindow(): BrowserWindow {
const size = screen.getPrimaryDisplay().workAreaSize;
// ... (window setup continues)
}
Both repositories provide boilerplate code for creating Electron applications, but with different frontend frameworks and build tools. The choice between them depends on project requirements and team preferences.
:electron: A complete tool for building and publishing Electron applications
Pros of Electron Forge
- More mature and widely adopted project with extensive documentation
- Offers a broader range of templates and customization options
- Provides built-in support for various packaging and distribution formats
Cons of Electron Forge
- Steeper learning curve for beginners
- Requires more configuration and boilerplate code
- May have slower build times for complex projects
Code Comparison
Electron Forge (main process):
const { app, BrowserWindow } = require('electron');
function createWindow() {
const win = new BrowserWindow({ width: 800, height: 600 });
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
vite-electron-builder (main process):
import { app, BrowserWindow } from 'electron';
import { join } from 'path';
async function createWindow() {
const win = new BrowserWindow({ width: 800, height: 600 });
await win.loadFile(join(__dirname, '../renderer/index.html'));
}
app.whenReady().then(createWindow);
Both repositories provide solid foundations for Electron app development, but vite-electron-builder offers a more streamlined setup with Vite integration, while Electron Forge provides a more comprehensive toolkit with greater flexibility.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
[!Important] This project is maintained by developer from Ukraine ðºð¦
I do my best, but due to Russia's ongoing full-scale invasion of Ukraine, I barely have the energy to support open source projects.
If my work has been useful to you, please consider supporting Ukraine or me personally. Even your $1 has an impact!
Vite Electron Builder Boilerplate
This is a template for secure electron applications. Written following the latest safety requirements, recommendations and best practices.
Get started
Follow these steps to get started with the template:
- Click the Use this template button (you must be logged in) or just clone this repo.
- Go to project folder and run
npm run init
. - Start application in development mode by
npm start
. - Compile executable by
npm run compile
.
That's all you need. ð
[!TIP] You can explore the demo application for various frameworks and operating systems in the Deployment section. This will allow you to see how the application performs across different environments. Additionally, you can verify the auto-update functionality by installing an outdated version of the application.
â¤ï¸ If you like this template, give a â or send support!
Features
Lightweight
When designing this template, I tried to keep Ñе minimal, using the platform's native features to the maximum and minimizing the number of third-party dependencies.
Electron
- This template uses the latest electron version with all the latest security patches.
- The architecture of the application is built according to the security guides and best practices.
- The latest version of the electron-builder is used to package the application.
Automatic tests
- End-to-end are placed in the root
tests
directory and use playwright. - You may write any unit tests inside each package and use whatever you
wantneed.
Continuous Integration
- The configured workflow will check the types for each push and PR.
- Code signing supported. See code-signing documentation.
Auto-update
Each time you push changes to the main
branch,
the ci
workflow starts to create and deploy a new application version with then will be downloaded and applied by each app instance.
Project Structure
The project is designed as monorepo where each part of the application is an independent package.
Each package could have own tech stack, tests, dependencies, frameworks, etc.
All internal names are prefixed by @vite-electron-builder/*
.
There are no technical reasons for this.
It's just for you to make it easier to understand the architecture.
Initially, the repository contains only a few packages.4
Packages with building tools:
packages/integrate-renderer
- A helper package that is not included in the runtime. It is used innpm run init
to configure a new interface package.packages/electron-versions
- A set of helper functions to get the versions of internal components bundled within Electron.
Packages with app logic:
packages/main
- Implementation of Electron's main script.packages/preload
- Implementation of Electron's preload scripts.
Renderer is not included
As you may have noticed, the repository does not contain a package that implements the application interface. The reason is that since the entire application is a mono-repository, you can use any web application based on any framework or bundler as a package for the interface.
There is only one requirement: the template expects to import renderer by @vite-electron-builder/renderer
name.
[!TIP] You can create new renderer package in interactive mode by
npm run init
.
[!NOTE] If you are using a bundler other than vite, you may need to slightly change the dev-mode.js script to run it correctly.
How It works
Compile executable
When an application is ready to distribute, you need to compile it into executable. We are using electron-builder for this.
- You can compile application locally by
npm run compile
. In this case, you will get executable that you cat share, but it will not support auto-updates out-of-box. - To have auto-updater, you should compile an application and publish it to one or more supported sources for distribution. In this case, all application instances will download and apply all new updates. This is done by GitHub action in release.yml.
[!TIP] This template is configured to use GitHub Releases to distribute updates, but you can configure whatever you need. Find more in electron-builder docs.
Working with third-party dependencies
Because the renderer
works and builds like a regular web application, you can only use dependencies that support the
browser or compile to a browser-friendly format.
This means that in the renderer
you are free to use any frontend dependencies such as Vue, React, lodash, axios and so
on. However, you CANNOT use any native Node.js APIs, such as, systeminformation
. These APIs are only available in
a Node.js runtime environment and will cause your application to crash if used in the renderer
layer. Instead, if you
need access to Node.js runtime APIs in your frontend, export a function form the preload
package.
All dependencies that require Node.js api can be used in
the preload
script.
Expose in the main world
Here is an example. Let's say you need to read some data from the file system or database in the renderer.
In the preload context, create a function that reads and returns data. To make the function announced in the preload
available in the render, you usually need to call
the electron.contextBridge.exposeInMainWorld
.
However, this template is designed to use all power of ES modules.
You can import anything from preload
in renderer
.
All the data will quietly throw through the electron.contextBridge.exposeInMainWorld()
,
so you don't need to worry about it.
// preload/src/index.ts
import {readFile} from 'node:fs/promises';
// Encapsulate types if you use typescript
interface UserData {
prop: string
}
// Will call `electron.contextBridge.exposeInMainWorld('getUserData', getUserData)`
export function getUserData(): Promise<UserData> {
return readFile('/path/to/file/in/user/filesystem.json', {encoding: 'utf8'}).then(JSON.parse);
}
Now you can import and call the method in renderer
// renderer/src/anywere/component.ts
import {getUserData} from '@vite-electron-builder/preload'
// Method will came from exposed context
// const userData = globalThis['getUserData']
const userData = await getUserData()
[!TIP] Find more in Context Isolation tutorial.
Working with Electron API
Although the preload has access to all of Node.js API, it still runs in the BrowserWindow context, so only limited electron modules are available in it.
[!TIP] Check the electron docs for the full list of available methods.
All other electron methods can be invoked in the main
.
As a result, the architecture of interaction between all modules is as follows:
sequenceDiagram
renderer->>+preload: Read data from file system
preload->>-renderer: Data
renderer->>preload: Maximize window
activate preload
preload-->>main: Invoke IPC command
activate main
main-->>preload: IPC response
deactivate main
preload->>renderer: Window maximized
deactivate preload
[!TIP] Find more in Inter-Process Communication tutorial.
Modes and Environment Variables
All environment variables are set as part of the import.meta
, so you can access them vie the following
way: import.meta.env
.
[!NOTE] If you are using TypeScript and want to get code completion, you must add all the environment variables to the
ImportMetaEnv
intypes/env.d.ts
.
The mode option is used to specify the value of import.meta.env.MODE
and the corresponding environment variables files
that need to be loaded.
By default, there are two modes:
production
is used by defaultdevelopment
is used bynpm start
script
When running the build script, the environment variables are loaded from the following files in your project root:
.env # loaded in all cases
.env.local # loaded in all cases, ignored by git
.env.[mode] # only loaded in specified env mode
.env.[mode].local # only loaded in specified env mode, ignored by git
[!WARNING] To prevent accidentally leaking env variables to the client, only variables prefixed with
VITE_
are exposed to your Vite-processed code.
For example, let's take the following .env
file:
DB_PASSWORD=foobar
VITE_SOME_KEY=123
Only VITE_SOME_KEY
will be exposed as import.meta.env.VITE_SOME_KEY
to your client source code, but DB_PASSWORD
will not.
[!TIP] You can change that prefix or add another. See
envPrefix
.
NPM Scripts
npm start
Start application in development more with hot-reload.
npm run build
Runs the build
command in all workspaces if present.
npm run compile
First runs the build
script,
then compiles the project into executable using electron-builder
with the specified configuration.
npm run compile -- --dir -c.asar=false
Same as npm run compile
but pass to electron-builder
additional parameters to disable asar archive and installer
creating.
Useful for debugging compiled application.
npm run test
Executes end-to-end tests on compiled app using Playwright.
npm run typecheck
Runs the typecheck
command in all workspaces if present.
npm run create-renderer
Initializes a new Vite project named renderer
. Basically same as npm create vite
.
npm run integrate-renderer
Starts the integration process of the renderer using the Vite Electron builder.
npm run init
Set up the initial environment by creating a new renderer, integrating it, and installing the necessary packages.
Contribution
See Contributing Guide.
Top Related Projects
🥳 Really simple Electron + Vite + Vue boilerplate.
Clone to try a simple Electron app
A Foundation for Scalable Cross-Platform Apps
Easily Build Your Vue.js App For Desktop With Electron
Ultra-fast bootstrapping with Angular and Electron :speedboat:
:electron: A complete tool for building and publishing Electron applications
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot