Vue CLI Plugin Electron Builder — Auto Update (Private GitHub Repository)
When building electron apps, you might want to notify the user when a new update is available and let them install and use this new version without having to uninstall and install the app again. Let’s get right into it and see how we can do this, using a private GitHub repository (you can follow along if you are using a public repository).
Requirements
Project Scaffold
First, create your GitHub repository, clone it in your local machine an navigate to the root folder. Now is time to create a Vue app:
vue create .
After having the vue initial scaffold, add electron-builder:
vue add electron-builder
To check if the app is running properly, run the following command:
npm run electron:serve
Note: more scripts/commands can be found in package.json.
Auto Updater & Build
Add electron-updater:
npm install electron-updater
In background.js import electron-updater and check for updates:
import { autoUpdater } from “electron-updater”;
...
//Inside createWindow(), at the end
autoUpdater.autoDownload = false;
autoUpdater.checkForUpdates();
In the root of the project create a file named vue.config.js and paste the following configurations:
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
publish: [
{
provider: “github”,
owner: “<your_username_here>”,
private: true,
}
]
}
}
}
};
More build options here.
Edit package.json to have a project description, author(s) and private set to true:
“description”: “<your_description_here”,
“author”: “<your_username_here>”,
“private”: true,
Note: If you set “private”: true in your package.json, then npm will refuse to publish it. This is a way to prevent accidental publication of private repositories.
For being able to publish releases, set the GH_TOKEN environment variable on your machine — get token here (add repo permissions):
// Windows terminal
set GH_TOKEN=<your_token_here>// Linux / macOS terminal
export GH_TOKEN=<your_token_here>
To receive updates in production, we also need to set process.env.GH_TOKEN since the repository is private. Be aware of security risks.
// Code at the end of createWindow function
process.env.GH_TOKEN = “<your_token_here>”;
autoUpdater.autoDownload = false;
autoUpdater.checkForUpdates();
Keep going :)
Debugging
If you want to log auto updater information, just use these two lines of code below (after npm install electron-log)(paste them near your imports in background.js):
autoUpdater.logger = require(“electron-log”);
autoUpdater.logger.transports.file.level = “info”;
In case you want to log your own strings, try:
const log = require(“electron-log”);
...
log.info("<your_string_here>");
I recommend to use both :)
Logs locations by default:
- on Linux:
~/.config/{app name}/logs/{process type}.log
- on macOS:
~/Library/Logs/{app name}/{process type}.log
- on Windows:
%USERPROFILE%\AppData\Roaming\{app name}\logs\{process type}.log
More about electron-log here.
“In order to develop/test UI/UX of updating without packaging the application you need to have a file named dev-app-update.yml
in the root of your project, which matches your publish
setting from electron-builder config (but in yaml format). But it is not recommended.” — Learn more here.
// dev-app-update.yml
provider: github
private: true
owner: <your_username_here>
repo: <your_repository_name_here>
token: <your_token_here>
Update the config path when dev server running:
if (process.env.WEBPACK_DEV_SERVER_URL) {
...
autoUpdater.updateConfigPath = path.join(
__dirname,
"../dev-app-update.yml" // change path if needed
);
} else {
...
Communication between main and renderer
You might want to show to the user relevant information about the updates — if there are any available or not, download progress, errors, etc. To do this, we need to listen to those events:
// Code after app.on("ready" ...)autoUpdater.on(“update-available”, () => {
log.info(“update_available”);
win.webContents.send(“updater”, “update_available”);
});autoUpdater.on(“update-not-available”, () => {
log.info(“update_not_available”);
win.webContents.send(“updater”, “update_not_available”);
});
The previous code checks if an update is available or not, logs and sends a message to the renderer process. More events here.
For ipcRenderer to work with vue, we need to preload it. Create a preload.js file in the same folder as background.js and paste the following code:
window.ipcRenderer = require(“electron”).ipcRenderer;
You also need to add a new line in vue.config.js:
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
publish: [
{
provider: “github”,
owner: “<your_username_here>”,
private: true,
}
]
},
preload: "src/preload.js", // this one
}
}
};
And in background.js, add the following:
win = new BrowserWindow({
...
webPreferences: {
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
preload: path.join(__dirname, “preload.js”),
},
});
Now you have access to window.ipcRenderer inside vue script tags.
Next, let’s clear the HelloWorld component. Should look something like:
<template>
<div class=”hello”>
<h1>{{ msg }}</h1>
<p>Updates State: {{ state }}</p>
</div>
</template><script>
export default {
name: “HelloWorld”,
data: function() {
return {
state: “Thinking…”,
};
},
props: {
msg: String,
}
</script>
<style scoped ...>
...
</style>
Finally, on a mounted hook:
...
mounted() {
window.ipcRenderer.on(“updater”, (event, message) => {
switch (message) {
case “update_available”:
this.state = “Available”;
break;
case “update_not_available”:
this.state = “Not Available”;
break;
}
});
},
...
That’s it! Now let’s build the app and wrap up.
Build & End
Build and release in GitHub with the command:
npm run electron:build — -p always
Go to your Repository > Releases and click edit. Publish the release.
Now change your version in package.json and do the previous steps again.
After that, install the oldest version in your machine and see what happens. Enjoy!
Questions, Opinions or Issues?
Let me know in the comments.
Consider leaving a thumbs up!