This guide will show you how to prepare sample Electron application for publishing from scratch:
- create a new app
- build distos
- publish release to GitHub
- set up autoupdating
Your app's updates may be stored on GitHub repo's releases page. It is free and user-friendly.
Create a new package.json
file.
{
"name": "self-updating-test-app",
"version": "0.0.1",
"main": "src/main.js",
"scripts": {
"start": "electron ."
}
}
And install electon
as a dev-dependency
yarn add -D electron
Now you need to create main script file in the sources directory: src/main.js
const { app, BrowserWindow } = require('electron');
/* Init application */
const init = () => {
/* Create the browser window */
const mainWindow = new BrowserWindow();
/* Text content to be shown in the window */
let content = `${app.getName()} v${app.getVersion()}`;
/* Load plain text content */
mainWindow.webContents.loadURL('data:text/plain;charset=utf-8,' + encodeURI(content));
};
app.on('ready', init);
The structure of your project will look like this:
self-updating-test-app
|-- node_modules/
|-- src/
| |-- main.js
|-- package.json
|-- yarn.lock
Run the app
yarn start
Now we are going to build a package for distribution
For building I prefer use electron-builder
tool.
Add it to your dev-dependencies.
yarn add -D electron-builder
Then add a new node script to your package.json
file
{
"name": "self-updating-test-app",
"version": "0.0.1",
"main": "src/main.js",
"scripts": {
"start": "electron .",
"dist": "electron-builder",
},
"devDependencies": {
"electron": "^5.0.1",
"electron-builder": "^20.40.2"
}
}
And now you can build a distro file for running OS
yarn dist
electron-builder
will create a dist
directory and put here release files. You should add dist
directory to .gitignore
file:
.idea/
dist/
node_modules/
.DS_Store
My dist
directory looks like
|-- dist
| |-- mac/
| |-- builder-effective-config.yaml
| |-- self-updating-test-app-0.0.1-mac.zip
| |-- self-updating-test-app-0.0.1.dmg
| |-- self-updating-test-app-0.0.1.dmg.blockmap
I can send self-updating-test-app-0.0.1.dmg
to my friend and he will be able to install and run my app.
Auto-updating will not work if you have not code-sign your app.
Read more about Code Signing.
While an application is under development you can use a free certificate.
Next step is a release publishing. You can use GitHub repo's releases page for it. electron-builder
can ship distros automatically after building.
GitHub's guide «Creating a personal access token for the command line».
Open your profile's settings: Settings
> Developer settings
> Personal access tokens
> Generate new token
Select the repo
scope
New token will be generated
Save it somewhere and use in console before shipping a release.
export GH_TOKEN=e4b064b76f30966c1347948219a9cc27
You will see an error if you skip the token:
Error: GitHub Personal Access Token is not set, neither programmatically, nor using env "GH_TOKEN"
Add repository info and two more scripts to package.json
file
yarn ship
— for building and publishing release for current OS
yarn ship:all
— for building and publishing release for macOS, Windows and Linux
{
"name": "self-updating-test-app",
"version": "0.0.1",
"main": "src/main.js",
"scripts": {
"start": "electron .",
"dist": "electron-builder",
"ship": "electron-builder -p always",
"ship:all": "electron-builder -mwl --x64 --ia32 -p always"
},
"repository": {
"type" : "git",
"url" : "https://github.com/talyguryn/self-updating-test-app.git"
},
"devDependencies": {
"electron": "^5.0.1",
"electron-builder": "^20.40.2"
}
}
Run yarn ship
. App will be built and sent to release draft.
...
• building target=macOS zip arch=x64 file=dist/self-updating-test-app-0.0.1-mac.zip
• building target=DMG arch=x64 file=dist/self-updating-test-app-0.0.1.dmg
• building block map blockMapFile=dist/self-updating-test-app-0.0.1.dmg.blockmap
• publishing publisher=Github (owner: talyguryn, project: self-updating-test-app, version: 0.0.1)
• uploading file=self-updating-test-app-0.0.1.dmg.blockmap provider=GitHub
• uploading file=self-updating-test-app-0.0.1.dmg provider=GitHub
• creating GitHub release reason=release doesn't exist tag=v0.0.1 version=0.0.1
[====================] 100% 0.0s | self-updating-test-app-0.0.1.dmg to GitHub
• building embedded block map file=dist/self-updating-test-app-0.0.1-mac.zip
• uploading file=self-updating-test-app-0.0.1-mac.zip provider=GitHub
[====================] 100% 0.0s | self-updating-test-app-0.0.1-mac.zip to GitHub
✨ Done in 94.48s.
Open releases page and see this draft. You can edit it and publish.
Now you can publish releases. It is time to set up autoupdating.
There are two packages that helps you to check available updates, download and install them:
- update-electron-app is the simplest method to get updates and notify user.
- electron-updater allow you define listeners for autoupdates events such as
checking-for-update
,update-available
,update-not-available
,download-progress
anderror
.
Install dependency
yarn add update-electron-app
And add to any place in main process.
require('update-electron-app')();
Our main.js
for example
const { app, BrowserWindow } = require('electron');
/* Check for updates */
require('update-electron-app')();
/* Init application */
const init = () => {
/* Create the browser window */
const mainWindow = new BrowserWindow();
/* Text content to be shown in the window */
let content = `${app.getName()} v${app.getVersion()}`;
/* Load plain text content */
mainWindow.webContents.loadURL('data:text/plain;charset=utf-8,' + encodeURI(content));
};
app.on('ready', init);
Bump version to 0.0.2
. Build and publish app with enabled autoupdating. Then install and run it.
It will check update.electronjs.org
server for info about updates every 10 minutes.
App send requests to https://update.electronjs.org/[OWNER]/[REPO]/[PLATFORM]-[ARCH]/[VERSION]
with app's params.
For example:
https://update.electronjs.org/talyguryn/self-updating-test-app/darwin/0.0.2
Then you can build same app with bumped version 0.0.3
for example. Release it too.
A few minutes later your runned 0.0.2
app will see and start downloading latest update. Then it will notify user and ask to restart app right now to use new version.
Install dependency
yarn add electron-updater
Require autoUpdater
from electron-updater
package.
const { autoUpdater } = require('electron-updater');
Then call checkForUpdates()
function
autoUpdater.checkForUpdates();
Application will check for updates and download them automatically.
If you do not need to download it without asking user then disable
autoDownload
option.
autoUpdater.autoDownload = false
Then if you want to download available update then call
downloadUpdate()
.
A successfully downloaded update will be applied the next time the application starts.
You can also use checkForUpdatesAndNotify()
function to show a notification.
See Events section on docs page for more information.
Here is a list of available events listeners
autoUpdater.on('error', (error) => {});
autoUpdater.on('checking-for-update', () => {});
autoUpdater.on('update-available', (updateInfo) => {});
autoUpdater.on('update-not-available', (updateInfo) => {});
autoUpdater.on('download-progress', (updateInfo) => {});
autoUpdater.on('update-downloaded', (info) => {});
Final version of main.js
.
const { app, BrowserWindow } = require('electron');
const { autoUpdater } = require('electron-updater');
/* Init application */
const init = () => {
/* Create the browser window */
const mainWindow = new BrowserWindow();
/* Text content to be shown in the window */
let content = `${app.getName()} v${app.getVersion()}`;
/* Load plain text content */
mainWindow.webContents.loadURL('data:text/plain;charset=utf-8,' + encodeURI(content));
/* Update is ready */
autoUpdater.on('update-downloaded', (updateInfo) => {
/* Notify user about ready to be installed update */
// ...
/* Or force quit app and install update */
// autoUpdater.quitAndInstall();
});
/* Check for updates manually */
autoUpdater.checkForUpdates();
/* Check updates every 10 minutes */
setInterval(() => {
autoUpdater.checkForUpdates();
}, 10 * 60 * 1000);
};
app.on('ready', init);
Use elecron-log
package to work with logs easily. See docs.
yarn add electron-log
Example main.js
file with defined autoUpdater.logger
const { app, BrowserWindow } = require('electron');
const { autoUpdater } = require('electron-updater');
const logger = require('electron-log');
/* Init application */
const init = () => {
/* Create the browser window */
const mainWindow = new BrowserWindow();
/* Text content to be shown in the window */
let content = `${app.getName()} v${app.getVersion()}`;
/* Load plain text content */
mainWindow.webContents.loadURL('data:text/plain;charset=utf-8,' + encodeURI(content));
/* Define logger for autoUpdater logs */
autoUpdater.logger = logger;
/* Check for updates manually */
autoUpdater.checkForUpdates();
/* Check updates every 10 minutes */
setInterval(() => {
autoUpdater.checkForUpdates();
}, 10 * 60 * 1000);
};
app.on('ready', init);
Example log file ~/Library/Logs/self-updating-test-app/log.log
[2019-05-22 13:23:09.761] [info] Checking for update [2019-05-22 13:23:17.237] [info] Found version 0.0.3 (url: self-updating-test-app-0.0.3-mac.zip, self-updating-test-app-0.0.3.dmg) [2019-05-22 13:23:17.237] [info] Downloading update from self-updating-test-app-0.0.3-mac.zip, self-updating-test-app-0.0.3.dmg [2019-05-22 13:23:17.258] [debug] updater cache dir: /Users/taly/Library/Application Support/Caches/self-updating-test-app-updater [2019-05-22 13:23:17.275] [info] No cached update info available [2019-05-22 13:24:34.305] [info] New version 0.0.3 has been downloaded to /Users/taly/Library/Application Support/Caches/self-updating-test-app-updater/pending/self-updating-test-app-0.0.3-mac.zip [2019-05-22 13:24:34.423] [info] / requested [2019-05-22 13:24:34.432] [info] /1558520674320-6689.zip requested [2019-05-22 13:24:34.432] [info] /1558520674320-6689.zip requested by Squirrel.Mac, pipe /Users/taly/Library/Application Support/Caches/self-updating-test-app-updater/pending/self-updating-test-app-0.0.3-mac.zip [2019-05-22 13:24:39.726] [info] Proxy server for native Squirrel.Mac is closed (was started to download https://github.com/talyguryn/self-updating-test-app/releases/download/v0.0.3/self-updating-test-app-0.0.3-mac.zip)
Example main.js
file with enabled logs for all events
const { app, BrowserWindow } = require('electron');
const { autoUpdater } = require('electron-updater');
const logger = require('electron-log');
/* Init application */
const init = () => {
/* Create the browser window */
const mainWindow = new BrowserWindow();
/* Text content to be shown in the window */
let content = `${app.getName()} v${app.getVersion()}`;
/* Load plain text content */
mainWindow.webContents.loadURL('data:text/plain;charset=utf-8,' + encodeURI(content));
/**
* Autoupdater events
*/
autoUpdater.on('checking-for-update', () => {
logger.log('Checking for update');
});
autoUpdater.on('error', (error) => {
logger.error('Error while checking for updates', error);
});
autoUpdater.on('update-available', (updateInfo) => {
logger.log('Update is available:', updateInfo);
});
autoUpdater.on('update-not-available', (updateInfo) => {
logger.log('No updates are available', updateInfo);
});
autoUpdater.on('download-progress', (progressInfo) => {
let logMessage = `speed ${progressInfo.bytesPerSecond} b/s; progress ${progressInfo.percent}%; downloaded ${progressInfo.transferred} out of ${progressInfo.total} bytes`;
logger.log(logMessage);
});
autoUpdater.on('update-downloaded', (updateInfo) => {
logger.log('Update is ready', updateInfo);
/* Notify user about ready to be installed update */
// ...
/* Or force quit app and install update */
// autoUpdater.quitAndInstall();
});
/* Check for updates manually */
autoUpdater.checkForUpdates();
/* Check updates every 10 minutes */
setInterval(() => {
autoUpdater.checkForUpdates();
}, 10 * 60 * 1000);
};
app.on('ready', init);
Example log file ~/Library/Logs/self-updating-test-app/log.log
[2019-05-22 13:08:45.117] [info] Checking for update [2019-05-22 13:08:52.371] [info] Update is available: { version: '0.0.3', files: [ { url: 'self-updating-test-app-0.0.3-mac.zip', sha512: '9I5RdFroVqNgB7fsQL5D2jV1vAxtL/A8pc2YgaCddIowEKB6yg3jLesiTt/g/Hhq4Z4N9A3SP1Fv5oopVcB18w==', size: 57172322, blockMapSize: 59483 }, { url: 'self-updating-test-app-0.0.3.dmg', sha512: 'xxRCF93tK+X6PDh8dWgKoXBSA2ias/K9XMNM6Z+fmqrv8yZc5pevkPgnOGIeCPkVTfzmPe2/2IUt1J1b0HtfFA==', size: 58915945 } ], path: 'self-updating-test-app-0.0.3-mac.zip', sha512: '9I5RdFroVqNgB7fsQL5D2jV1vAxtL/A8pc2YgaCddIowEKB6yg3jLesiTt/g/Hhq4Z4N9A3SP1Fv5oopVcB18w==', releaseDate: '2019-05-22T08:48:27.699Z', releaseName: '0.0.3', releaseNotes: '' } [2019-05-22 13:08:53.886] [info] speed 1469207 b/s; progress 2.716265398491249%; downloaded 1552952 out of 57172322 bytes [2019-05-22 13:08:54.885] [info] speed 2106855 b/s; progress 7.580241362245179%; downloaded 4333800 out of 57172322 bytes [2019-05-22 13:08:55.891] [info] speed 1873643 b/s; progress 10.03801804656456%; downloaded 5738968 out of 57172322 bytes [2019-05-22 13:08:56.893] [info] speed 1758388 b/s; progress 12.502287383045244%; downloaded 7147848 out of 57172322 bytes [2019-05-22 13:08:57.924] [info] speed 1711286 b/s; progress 15.253380822979343%; downloaded 8720712 out of 57172322 bytes [2019-05-22 13:08:58.926] [info] speed 1685342 b/s; progress 17.975859017935285%; downloaded 10277216 out of 57172322 bytes [2019-05-22 13:08:59.934] [info] speed 1612534 b/s; progress 20.03951492472179%; downloaded 11457056 out of 57172322 bytes [2019-05-22 13:09:00.942] [info] speed 1583630 b/s; progress 22.47516901622432%; downloaded 12849576 out of 57172322 bytes [2019-05-22 13:09:01.950] [info] speed 1543525 b/s; progress 24.62467065794529%; downloaded 14078496 out of 57172322 bytes [2019-05-22 13:09:02.958] [info] speed 1503133 b/s; progress 26.630424421103626%; downloaded 15225232 out of 57172322 bytes [2019-05-22 13:09:03.970] [info] speed 1478237 b/s; progress 28.80854130780275%; downloaded 16470512 out of 57172322 bytes [2019-05-22 13:09:05.009] [info] speed 1455722 b/s; progress 31.015273439480033%; downloaded 17732152 out of 57172322 bytes [2019-05-22 13:09:06.050] [info] speed 1438975 b/s; progress 33.27856440744177%; downloaded 19026128 out of 57172322 bytes [2019-05-22 13:09:07.091] [info] speed 1428167 b/s; progress 35.62904441768169%; downloaded 20369952 out of 57172322 bytes [2019-05-22 13:09:08.130] [info] speed 1421222 b/s; progress 38.03608326420606%; downloaded 21746112 out of 57172322 bytes [2019-05-22 13:09:09.130] [info] speed 1423388 b/s; progress 40.58619833562121%; downloaded 23204072 out of 57172322 bytes [2019-05-22 13:09:10.132] [info] speed 1433858 b/s; progress 43.395193919183484%; downloaded 24810040 out of 57172322 bytes [2019-05-22 13:09:11.144] [info] speed 1469054 b/s; progress 47.06331850576228%; downloaded 26907192 out of 57172322 bytes [2019-05-22 13:09:12.144] [info] speed 1488212 b/s; progress 50.280091824851894%; downloaded 28746296 out of 57172322 bytes [2019-05-22 13:09:13.152] [info] speed 1497298 b/s; progress 53.22432767379992%; downloaded 30429584 out of 57172322 bytes [2019-05-22 13:09:14.164] [info] speed 1497697 b/s; progress 55.88957537879955%; downloaded 31953368 out of 57172322 bytes [2019-05-22 13:09:15.177] [info] speed 1507442 b/s; progress 58.926821268515205%; downloaded 33689832 out of 57172322 bytes [2019-05-22 13:09:16.181] [info] speed 1506547 b/s; progress 61.53483848355853%; downloaded 35180896 out of 57172322 bytes [2019-05-22 13:09:17.198] [info] speed 1483957 b/s; progress 63.2544397969353%; downloaded 36164032 out of 57172322 bytes [2019-05-22 13:09:18.201] [info] speed 1461507 b/s; progress 64.8589084767276%; downloaded 37081344 out of 57172322 bytes [2019-05-22 13:09:19.201] [info] speed 1436474 b/s; progress 66.26307044167281%; downloaded 37884136 out of 57172322 bytes [2019-05-22 13:09:20.211] [info] speed 1414615 b/s; progress 67.75374979522434%; downloaded 38736392 out of 57172322 bytes [2019-05-22 13:09:21.217] [info] speed 1394493 b/s; progress 69.243757495104%; downloaded 39588264 out of 57172322 bytes [2019-05-22 13:09:22.225] [info] speed 1376768 b/s; progress 70.79099568494%; downloaded 40472856 out of 57172322 bytes [2019-05-22 13:09:23.236] [info] speed 1362832 b/s; progress 72.48198175333862%; downloaded 41439632 out of 57172322 bytes [2019-05-22 13:09:24.244] [info] speed 1351918 b/s; progress 74.28742880164985%; downloaded 42471848 out of 57172322 bytes [2019-05-22 13:09:25.251] [info] speed 1342270 b/s; progress 76.12149109493926%; downloaded 43520424 out of 57172322 bytes [2019-05-22 13:09:26.271] [info] speed 1341053 b/s; progress 78.44268420652917%; downloaded 44847504 out of 57172322 bytes [2019-05-22 13:09:27.273] [info] speed 1348180 b/s; progress 81.22239289144142%; downloaded 46436728 out of 57172322 bytes [2019-05-22 13:09:28.274] [info] speed 1370619 b/s; progress 84.97636321295468%; downloaded 48582960 out of 57172322 bytes [2019-05-22 13:09:29.284] [info] speed 1411334 b/s; progress 89.99141927452237%; downloaded 51450184 out of 57172322 bytes [2019-05-22 13:09:30.299] [info] speed 1447402 b/s; progress 94.8633991111993%; downloaded 54235608 out of 57172322 bytes [2019-05-22 13:09:31.284] [info] speed 1486733 b/s; progress 100%; downloaded 57172322 out of 57172322 bytes [2019-05-22 13:09:33.910] [info] Update is ready { version: '0.0.3', files: [ { url: 'self-updating-test-app-0.0.3-mac.zip', sha512: '9I5RdFroVqNgB7fsQL5D2jV1vAxtL/A8pc2YgaCddIowEKB6yg3jLesiTt/g/Hhq4Z4N9A3SP1Fv5oopVcB18w==', size: 57172322, blockMapSize: 59483 }, { url: 'self-updating-test-app-0.0.3.dmg', sha512: 'xxRCF93tK+X6PDh8dWgKoXBSA2ias/K9XMNM6Z+fmqrv8yZc5pevkPgnOGIeCPkVTfzmPe2/2IUt1J1b0HtfFA==', size: 58915945 } ], path: 'self-updating-test-app-0.0.3-mac.zip', sha512: '9I5RdFroVqNgB7fsQL5D2jV1vAxtL/A8pc2YgaCddIowEKB6yg3jLesiTt/g/Hhq4Z4N9A3SP1Fv5oopVcB18w==', releaseDate: '2019-05-22T08:48:27.699Z', releaseName: '0.0.3', releaseNotes: '', downloadedFile: '/Users/taly/Library/Application Support/Caches/self-updating-test-app-updater/pending/self-updating-test-app-0.0.3-mac.zip' }
- Auto Update // www.electron.build
- Creating and deploying an auto-updating Electron app for Mac and Windows using electron-builder // medium.com
- A complete guide to packaging your Electron app // medium.com
- Quick and painless automatic updates in Electron // medium.freecodecamp.org
- Updating Applications // electronjs.org