preface

Recently, the electron application has been carried out for a period of time, with slight gains. Now, the main thing I want to share with you is what I learned from electron- Updater.

Automatic updates

  • Download the new installation package update
  • Local file update

There are two types of updates using the new installation package, full updates and incremental updates. After comparing the solutions officially provided by Electron with those provided by the open source community, the electron- Updater was chosen. The electron-updater supports both full and incremental updates.

Whether it’s a full update or an incremental update, the basic process is to download a new installation package and wait for it to be reinstalled, but the latter requires only partial data download to form a new installation package.

In addition to this method, there is also a local file update. As we know, the parts of electron application that need to be updated are usually concentrated in the file app.asar, sometimes in app.asar. Unpacked.

For those of you who are not familiar with app.asar. Unpacked, this is the directory generated by using the asarUnpack feature. All files specified that do not need to be packed into the app.asar compressed file are stored in this directory. When electron starts up, it copies the files in this directory into app.asar before launching. There is a microelectron – Asar-hot-updater in the community. The general workflow is to check whether there is a new version of the compressed file app.asar, if so, download and overwrite the app.asar in the application installation directory, and then restart.

Full quantity update

Figure 1

The general logic for full updates is shown in Figure 1. When packaged as an installer, update. Yml files are generated along with it.

As shown in Figure 2, update.yml records information about the new version of the installer, and the three most important fields are Version, PATH, and SHA512. .yml files are very common file format, we can use JS-YAMl can be used to parse yamL files.

const yaml = require('js-yaml');
const fs   = require('fs');

// Get document, or throw exception on error
try {
  const doc = yaml.load(fs.readFileSync('/home/ixti/example.yml'.'utf8'));
  console.log(doc);
} catch (e) {
  console.log(e);
}
Copy the code

Update.yml is uploaded to the server with the new installer, and you can follow the logic shown in Figure 1. You can use semver when comparing remote latest version numbers with local version numbers.

const semver = require('semver')

semver.valid("1.2.3") / / "1.2.3"
semver.valid('a.b.c') // null
semver.clean('= v1.2.3') / / "1.2.3"
semver.satisfies("1.2.3".'1. X | | > = 2.5.0 | | 5.0.0-7.2.3') // true
semver.gt("1.2.3".'9.8.7') // false
semver.lt("1.2.3".'9.8.7') // true
semver.minVersion('> = 1.0.0') / / '1.0.0'
semver.valid(semver.coerce('v2')) / / '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3 - alpha')) / / '42.6.7'
Copy the code

Incremental updating

An incremental update is a version update that requires only a portion of the data to be requested. I will focus on the incremental update scheme used in electron-updater.

The electron updater adopts the software incremental update mode based on content-defined Chunking (CDC), which solves the problem that non-adjacent versions need to be patched separately in other incremental updates. You only need to download some files to generate the installation package of a new version.

Variable length chunks of content — CDC

The core operation is to determine the boundary of each window. It applies data fingerprint such as Rabin fingerprint algorithm to divide the file into content blocks with different growth degrees. During algorithm execution, CDC uses a fixed-size sliding window to compute a data fingerprint on the file data.

As shown in Figure 3, generally a corresponding program uses the fingerprint algorithm to divide the installer into data blocks of different sizes, then calculates the hash value and size of the different data blocks and records them into a BlockMap file. Therefore, each version of the installer has its own BlockMap file. Then, compare the two versions of blockMap files and calculate the different data blocks. Then, use segmenced requests (range: bytes=x-y) to request the data of the latest installer and write the data into the old installer to generate a new installer.

The update to the electron-updater is to generate blockmap files using app-Builder-bin compilation. The Blockmap file uses gzip compression. The actual file content is shown as follows.

{
    "version": "2"."files": [{"name": "file"."offset": 0."checksums": [
                "VxFZSGxhDYz5FXgMiOUk5oCc"]."sizes": [
                32768]]}}Copy the code

Local update

As figure 4 shows, the logic for partial file updates is simpler than for full updates. Here, the electron- Asar-hot-update network request does not use the NET API provided by Electron, but instead uses the Request library.

Note that in Windows, if you replace app.asar directly with nodejs in the main application process, an error will be reported due to file occupation, because the main process code is also in app.asar. So the library writes a separate update.exe program that is called to handle the file replacement asynchronously.

Ps: Unix-like system, usually does not have the problem of file occupancy, you can try to write a Nodejs script in the MAC system, let it delete itself, see if there is an error.

Gray released

Full, incremental, and partial updates are basically all covered, and when we’re done with the updates, we’re ready to release the app.

Wait a minute! Do YOU publish your application directly by Posting the download link for the application installation package on the official website? Of course not. We want everyone to be able to use our app the first time we install it, but after a while, we add a new feature, and how do we release it?

Answer this question first and then why. We definitely don’t update the old version to the latest version directly through the update logic described earlier. Although, the new version through various internal tests, internal feel has been very stable, but released to the user or to be cautious. We hope that some users can use the new version first, collect some feedback, fix some undiscovered bugs in time, and then gradually expand the scope of users to experience the new version. This is greyscale publishing.

Grayscale publishing (also known as canary publishing) is a smooth transition between black and white publishing. A/B testing can be carried out on it, that is, some users continue to use product feature A and some users start to use product feature B. If users have no objection to B, the scope can be gradually expanded to migrate all users to B. Grayscale publishing can ensure the stability of the whole system, and problems can be found and adjusted at the beginning of the grayscale to ensure its impact.

This is baidu Encyclopedia on the gray release of the explanation.

As shown in Figure 5, the key point is to generate a constant GUID first, then hash the GUID, obtain hashCode and mod 100 to get a number of 0-100, and determine whether the current application needs to be updated to a new version according to the progress of grayscale publishing.

The electron-updater itself contains the logic of grayscale publishing. It generates a constant stagingUserId and writes it to a local file as a unique ID, then calculates a number from 0 to 100 and compares it with the stagingPercentage field in update.yml on the server to determine whether to update the new version.

As for how to promote grayscale publishing, we can have their own implementation.

conclusion

During the Spring Festival, I have been writing intermittently for several days. I hope this summary will be helpful for you to develop the electron application. Thank you for your reading