Cross-Platform Auto-Update Implementation for Electron Applications
Auto-Update Implementation
The following code demonstrates how to implement automatic updates for Electron applications that work seamlessly on both Windows and macOS platforms.
Main Process Update Handler
import { ipcMain } from 'electron'
import log from './logger'
import { autoUpdater } from 'electron-updater'
const fs = require('fs-extra')
const path = require('path')
// Function to handle application updates
export function updateHandler({ mainWindow }) {
// Clear previous update download files to ensure proper updating
// The updaterCacheDirName value should match the one in app-update.yml
const updaterCacheDirName = 'workbench-updater'
const updatePendingPath = path.join(autoUpdater.app.baseCachePath, updaterCacheDirName, 'pending')
fs.emptyDir(updatePendingPath)
const updateMessages = {
error: 'Update check failed',
checking: 'Checking for updates...',
updateAvailable: 'New version detected. Downloading...',
updateNotAvailable: 'You are using the latest version'
}
// Configure update server URL
autoUpdater.setFeedURL({
provider: 'generic',
url: 'your-update-server-url'
})
// Configure update download settings
autoUpdater.disableWebInstaller = false
autoUpdater.autoDownload = false
autoUpdater.logger = log
// Event handlers for update process
autoUpdater.on('error', () => {
sendUpdateMessage(updateMessages.error, mainWindow)
console.log(updateMessages.error)
})
autoUpdater.on('checking-for-update', () => {
if (process.env.NODE_ENV !== 'development') {
sendUpdateMessage(updateMessages.checking, mainWindow)
console.log(updateMessages.checking)
}
})
autoUpdater.on('update-available', () => {
sendUpdateMessage(updateMessages.updateAvailable, mainWindow)
console.log(updateMessages.updateAvailable)
})
autoUpdater.on('update-not-available', () => {
sendUpdateMessage(updateMessages.updateNotAvailable, mainWindow)
console.log(updateMessages.updateNotAvailable)
})
autoUpdater.on('download-progress', (progressObj) => {
mainWindow.webContents.send('downloadProgress', progressObj)
})
autoUpdater.on('update-downloaded', () => {
log.warn('Starting update process')
autoUpdater.quitAndInstall()
})
ipcMain.on('checkForUpdate', () => {
log.warn('Checking for updates, window destroyed:', mainWindow.isDestroyed())
if (mainWindow && !mainWindow.isDestroyed()) {
autoUpdater.checkForUpdates()
}
})
ipcMain.on('downloadUpdate', () => {
log.warn('Downloading update')
autoUpdater.downloadUpdate()
})
}
// Helper function to send messages to renderer process
function sendUpdateMessage(text, mainWindow) {
mainWindow.webContents.send('message', text)
}
Logging Configuration
const log = require('electron-log')
log.transports.file.fileName = 'main.log';
log.transports.file.level = 'false';
// When reaching max size, backup file as main.old.log (only one backup)
log.transports.file.maxSize = 1048576;
log.transports.console.level = 'silly';
export default log
Renderer Process Update UI
<template>
<el-dialog
v-model="isProgressVisible"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
fullscreen
title="Downloading new version, please wait..."
>
<div style="text-align:center">
<el-progress type="circle" :percentage="percentage"></el-progress>
</div>
</el-dialog>
</template>
<script>
import { ipcRenderer } from 'electron'
import { ref, nextTick } from 'vue'
export default {
setup() {
// Update progress visibility
const isProgressVisible = ref(false)
// Download progress percentage
const percentage = ref(0)
// Function to check for updates
const checkForUpdates = () => {
// Trigger update check
ipcRenderer.send('checkForUpdate')
// Listen for update events
ipcRenderer.on('message', (event, text) => {
if (text === 'New version detected. Downloading...') {
nextTick(() => {
isProgressVisible.value = true
ipcRenderer.send('downloadUpdate')
// Listen for download progress
ipcRenderer.on('downloadProgress', (event, progressObj) => {
percentage.value = parseInt(progressObj.percent || 0)
console.log('Download progress:', percentage.value)
})
})
}
})
}
return {
isProgressVisible,
percentage,
checkForUpdates
}
}
}
</script>
Required Update Files
For Windows, the update process requires the installer package and the yml configuration file.
For macOS, in addition to the installer package and yml file, you also need a zip archive of the installer, making a total of three required files.
These files are automatically generated during the packaging process.