Getting Started: JS / Electron
Get started with our NPM package for JS & Electron.
This guide assumes you are building an Electron app with Electron Forge and the Webpack bundler. Since Velopack contains a native binary module (.node
), it may not be compatible with the vite
or rollup
bundlers. To scaffold a brand new project, you can use the official electron forge template:
npm init electron-app@latest my-new-app-name -- --template=webpack-typescript
-
Add Velopack to your
package.json
:npm install velopack
-
Add the following code to your entry point (eg.
index.ts
) as early as possible (before any electron startup code etc.):const { VelopackApp } = require('velopack');
// Velopack builder needs to be the first thing to run in the main process.
// In some cases, it might quit/restart the process to perform tasks.
VelopackApp.build().run();
// ... your other app startup code herewarningIf you currently have any "Squirrel" startup code you should remove this now. For example:
npm uninstall electron-squirrel-startup @electron-forge/maker-squirrel
-
Add auto-updates to your app: This has some complexity because of electron's IPC model and that Velopack has a native node module.
First, you should setup IPC handlers in your main application thread:
const { VelopackApp } = require('velopack');
ipcMain.handle("velopack:get-version", () => {
try {
const updateManager = new UpdateManager(updateUrl);
return updateManager.getCurrentVersion();
} catch (e) {
return `Not Installed (${e})`;
}
});
ipcMain.handle("velopack:check-for-update", async () => {
const updateManager = new UpdateManager(updateUrl);
return await updateManager.checkForUpdatesAsync();
});
ipcMain.handle("velopack:download-update", async (_, updateInfo) => {
const updateManager = new UpdateManager(updateUrl);
await updateManager.downloadUpdateAsync(updateInfo);
return true;
});
ipcMain.handle("velopack:apply-update", async (_, updateInfo) => {
const updateManager = new UpdateManager(updateUrl);
await updateManager.waitExitThenApplyUpdate(updateInfo);
app.quit();
return true;
});Next, you need to expose these functions to your renderer processes in
preload.ts
import { contextBridge, ipcRenderer } from "electron";
import type { UpdateInfo } from "velopack";
interface VelopackBridgeApi {
getVersion: () => Promise<string>,
checkForUpdates: () => Promise<UpdateInfo>,
downloadUpdates: (updateInfo: UpdateInfo) => Promise<boolean>,
applyUpdates: (updateInfo: UpdateInfo) => Promise<boolean>,
}
declare global {
interface Window {
velopackApi: VelopackBridgeApi;
}
}
const velopackApi: VelopackBridgeApi = {
getVersion: () => ipcRenderer.invoke("velopack:get-version"),
checkForUpdates: () => ipcRenderer.invoke("velopack:check-for-update"),
downloadUpdates: (updateInfo: UpdateInfo) => ipcRenderer.invoke("velopack:download-update", updateInfo),
applyUpdates: (updateInfo: UpdateInfo) => ipcRenderer.invoke("velopack:apply-update", updateInfo)
};
contextBridge.exposeInMainWorld("velopackApi", velopackApi);Lastly, you can now use these functions in your renderer to provide an update UI to your users:
async function updateApp() {
// check for new version
const updateInfo = await window.velopackApi.checkForUpdates();
if (!updateInfo) {
return; // no updates available
}
// download new version
await window.velopackApi.downloadUpdates(updateInfo);
// install new version and restart app
await window.velopackApi.applyUpdates(updateInfo);
}Review our Electron sample app for a more complete example.
-
Compile your app to a binary (eg.
.exe
on Windows). Example using electron forge:npx electron-forge package
-
Install the
vpk
command line tool:dotnet tool update -g vpk
tipYou must have the .NET Core SDK 8 installed to use and update
vpk
-
Package your Velopack release / installers:
vpk pack -u MyAppUniqueId -v 1.0.0 -p ./myBuildDir -e myexename.exe
✅ You're Done! Your app now has auto-updates and an installer.
You can upload your release to your website, or use the vpk upload
command to publish it to the destination of your choice.