Setting Up a Vite, Vue 3, and JavaScript Project
Ensure all JSON configuration files do not contain comments, as they may cause runtime issues even if no immediate errors are shown.
1. Creating the Desktop Application
1.1 Project Initialization
Run the following command to create a new project:
npm create vite@latest
When prompted, select the Vue 3 framwork with either JavaScript or TypeScript.
1.2 Installing Dependencies and Starting the Project
Navigate into the project directory and install the dependencies, then run the development server.
npm install
npm run dev
1.3 Integrating Electron
Install Electron as a dependency. Using a mirror is recommended for faster installation.
npm install electron
To configure an npm mirror, create a .npmrc file in your project root and add the following line:
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
1.4 Configuring Application Files
Vite Configuration (vite.config.js)
Set the base property to ensure static assets are correctly referenced when the application is built.
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
base: './', // Use relative paths for asset resolution
plugins: [vue()]
});
Electron Main Process (main.js)
Create a new main.js file in the project root. This is the entry point for the Electron application.
const { app, BrowserWindow } = require('electron');
const path = require('path');
function initializeWindow() {
const primaryWindow = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
});
primaryWindow.loadFile('dist/index.html');
// primaryWindow.webContents.openDevTools(); // Enable for debugging
}
app.whenReady().then(() => {
initializeWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
initializeWindow();
}
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
Preload Script (preload.js)
Create a preload.js file to safely expose Node.js APIs to the renderer process.
window.addEventListener('DOMContentLoaded', () => {
const updateElement = (id, content) => {
const targetElement = document.getElementById(id);
if (targetElement) targetElement.textContent = content;
};
['chrome', 'node', 'electron'].forEach(lib => {
updateElement(`${lib}-version`, process.versions[lib]);
});
});
Package Configuration (package.json)
Update your package.json to include the main entry point and the Electron start script. Remove the "type": "module" line if it exists.
{
"name": "my-electron-app",
"private": true,
"version": "0.0.0",
"main": "main.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"electron:start": "electron ."
},
"dependencies": {
"electron": "^27.0.0",
"vue": "^3.3.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"vite": "^4.4.5"
}
}
1.5 Building the Vue Application
Run the build command to generate the dist folder.
npm run build
1.6 Launching the Electron Application
Start the built application.
npm run electron:start
2. Implementing Hot Reload for Development
2.1 Modify the Main Process for Development
Update main.js to load the application from the Vite development server URL instead of a static file.
// ... previous app setup code
function initializeWindow() {
// ... window creation settings
// Replace loadFile with loadURL for development
primaryWindow.loadURL("http://localhost:5173");
}
// ... rest of the code
2.2 Running Both Servers Concurrently
Install concurrently and wait-on to run the Vite dev server and Electron simultaneously.
npm install -D concurrently wait-on
Update the scripts in package.json:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"electron:dev": "wait-on tcp:5173 && electron .",
"electron:start": "concurrently -k \"npm run dev\" \"npm run electron:dev\""
}
}
Run the application in development mode with hot reload:
npm run electron:start
3. Building the Application for Production
The key is to make the main process load the correct source based on the environment variable NODE_ENV.
3.1 Organizing Files
Create an electron folder in the project root and move main.js and preload.js into it.
3.2 Configuring the Main Process for Different Environments
Update electron/main.js to conditionally load resources.
const { app, BrowserWindow } = require('electron');
const path = require('path');
const appMode = process.env.NODE_ENV;
function initializeWindow() {
const primaryWindow = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
});
const appUrl = appMode === 'development'
? 'http://localhost:5173'
: `file://${path.join(__dirname, '../dist/index.html')}`;
primaryWindow.loadURL(appUrl);
if (appMode === 'development') {
primaryWindow.webContents.openDevTools();
}
}
// ... rest of the app lifecycle code
3.3 Updating Package Configuration for Building
Modify package.json to specify the new main entry point and add build configuration for electron-builder. Install the necessary build tools.
npm install -D cross-env electron-builder
Update package.json:
{
"name": "my-electron-app",
"private": true,
"version": "0.0.0",
"main": "electron/main.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"electron:dev": "wait-on tcp:5173 && cross-env NODE_ENV=development electron .",
"electron:start": "concurrently -k \"npm run dev\" \"npm run electron:dev\"",
"electron:build": "vite build && electron-builder"
},
"build": {
"appId": "com.example.myapp",
"productName": "MyElectronApp",
"copyright": "Copyright © 2023",
"mac": {
"category": "public.app-category.developer-tools"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
},
"files": [
"dist/**/*",
"electron/**/*"
],
"directories": {
"buildResources": "assets",
"output": "dist_electron"
}
},
"dependencies": {},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"concurrently": "^8.2.1",
"cross-env": "^7.0.3",
"electron": "^27.0.0",
"electron-builder": "^24.9.1",
"vite": "^4.4.5",
"vue": "^3.3.4",
"wait-on": "^7.0.1"
}
}
3.4 Executing the Production Build
Run the build command to generate the distributable application.
npm run electron:build
This command first builds the Vue application and then packages it with Electron, outputting the final executable to the dist_electron directory.
Alternative: Using Pre-configured Templates
Several community projects offer pre-configured setups for Vue, Electron, and TypeScript, which can simplify the initial process.
Using the create electron-vite Command
This method scaffolds a project with Vite, Vue 3, and TypeScript already configured.
npm create electron-vite
Follow the prompts to name your project and select the Vue template.
Using a Scaffolded Project Template
Another approach is to use a specific generator that supports multiple frontend frameworks.
yarn create electron-vite my-project
Select the Vue template when prompted. Development and build commands are typically yarn run dev and yarn run build.
Common Build Issues and Solutions
- TypeScript Compilation Errors: If
vue-tscfails during build, you may need to remove it from the build script inpackage.json. - Slow Binary Downloadss: Add mirror URLs to your
.npmrcfile to speed up downloads of Electron builder binaries. - Symbolic Link Permission Errors: On Windows, running the build command in an elevated (Administrator) PowerShell session can resolve permissions issues.