If you are using electron, you may find that you need to make new changes to the deployed application. To achieve this, you need to set up a server that contains update artifacts so that e-mail can listen to and update when a new version is released.
This tutorial will show you how to make your own simple update server. The server consists of two parts: back-end REST server, which can handle file upload; And static file server, which can display these files. This example runs on Ubuntu 18.04 EC2 instance (t2.micro, 30 GB EBS storage).
First, make sure the dependencies are installed
- Node - preferably node 10 +, installed through nvm
- Docker - this will be used to start an Apache server that will act as our static file server and publicly update artifacts
Create a REST server
Create a new folder for the application and set up the project. Use yarn or npm. Open the terminal and run.
npm i -g yarn mkdir simple-update-server cd simple-update-server yarn init # Make the necessary configuration or leave as default
Add the following packages as dependencies
yarn add express express-fileupload morgan
In package JSON file, add a script to start the server
"scripts": { "start": "node index.js", "prestart": "mkdir -p files/ && chown -R ubuntu:ubuntu files/" },
prestart hook creates a files / directory in your project and makes the current user the owner of the folder. Change ubuntu to the current user.
Create a file named config JS file. This allows us to create a custom authentication key to pass as a header to the REST server. This is completely optional
module.exports = { AUTH_TOKEN: '<Set an auth token here>', }
Finally, create an index for the main logic of the server JS file.
const path = require('path'); const express = require('express'); const fileUpload = require('express-fileupload'); const morgan = require('morgan'); const { AUTH_TOKEN } = require('./config'); const app = express(); const PORT = 3030; const FILES_STORE = path.join(__dirname, 'files/'); app.use(fileUpload()); app.use(morgan('dev')); app.get('/ping', (req, res) => { const authToken = req.get('Authorization'); if (!authToken || authToken !== AUTH_TOKEN) { return res.status(401).json({ message: 'Unauthorized' }); } return res.status(200).json({ message: 'Server is up!' }); }); app.post('/upload', (req, res) => { const authToken = req.get('Authorization'); if (!authToken || authToken !== AUTH_TOKEN) { return res.status(401).json({ message: 'Unauthorized' }); } if (!req.files || Object.keys(req.files).length === 0) { return res.status(400).json({ message: 'No files were uploaded.' }); } const files = req.files.File; if (Array.isArray(files)) { for (let index = 0; index < files.length; index += 1) { const file = files[index]; const path = `${FILES_STORE}${file.name}`; file.mv(path, (err) => { if (err) { console.log(err); return res.status(500).json({ message: 'An error occured during upload, please try again' }); } }); } } else { const path = `${FILES_STORE}${files.name}`; files.mv(path, (err) => { if (err) { console.log(err); return res.status(500).json({ message: 'An error occured during upload, please try again' }); } }); } return res.status(200).json({ message: 'Files were uploaded' }); }); app.listen(PORT, () => { console.log(`Express server listening on port ${PORT}`); });
Run the server with yarn start. You should see automatically created files / directories.
The server exposes 2 endpoints/ ping checks whether the server is up and running, and / upload receives files and moves them to the files / directory.
Test API: you can use Postman (with form data) or run the cURL command, as shown below. You can add any number of files, just add more - F flags. If successful, you should see the file uploaded to the files / directory.
curl -X POST -H 'Authorization: <Your Auth Token>' -F 'File=@<path/to/file1>' -F 'File=@<path/to/file2> http://<Your server IP>:3030/upload
Create a static file server
We can use docker to create an Apache container and mount the files / directory as a binding from an earlier location. Run the following command in the terminal.
docker run -dit --name simple-update-file-server -p 5080:80 -v ~/simple-update-server/files:/usr/local/apache2/htdocs/:ro httpd:2.4
-v flag installation directory source: destination. The following: ro makes it a read-only mount. Make sure to change the source directory to the location of the project. The original port number and container name can be set as your preferences.
Go to < your IP >: 5080 and make sure your files are there. If you see them, the server is finished!
Configure Electron
Now that the server is set up, we need to make some changes in the Electron client to listen to the server for updates. This example will use Electron builder and Electron Updater.
We need to set the general server option for electron builder so that electron can listen for updates here. In your application package JSON, set the following in the build attribute.
"publish": [ { "provider": "generic", "url": "http://<Your server IP>:5080/" } ],
In your electronic JS file, add the following to handle the update download event. You can also handle other events defined here.
const { dialog, } = require('electron'); const { autoUpdater } = require('electron-updater'); autoUpdater.on('update-downloaded', (info) => { const dialogOpts = { type: 'info', buttons: ['Restart', 'Update'], title: 'Application Update', detail: 'A new version has been downloaded. Restart the application to apply the updates.' }; dialog.showMessageBox(dialogOpts, (response) => { if (response === 0) { autoUpdater.quitAndInstall(); } }); });
On your app On ('ready '... Function event, make sure you call autoUpdater.checkForUpdates()
app.on('ready', function() { autoUpdater.checkForUpdates(); });
All steps
- Publishing applications using electron builder
- Upload artifacts from dist / folder
(except for the * - unpacked folder and the builder-effective-config.yaml file *) - Download application via file server
- Running applications
- Update package JSON, and then repeat 1-2 again.
- Run the application and you should now see the update prompt.
If you successfully see the update prompt, the update server has completed!