preface

This article contains packaging, automatic update, simple API, debugging, process communication and other related knowledge points, the content is more, may cause discomfort, please check (manual funny).

electron

Introduction to the

Developed by Github, Electron is an open source library that builds desktop applications using Html, CSS, and JavaScript, and can be packaged for Mac, Windows, and Linux operating systems.

Electron is a runtime environment containing Node and Chromium, which can be interpreted as running a Web application in Node

structure

Electron is mainly divided into the main process and the rendering process, as shown in the following figure

Electron running the main field in package.json indicates that the script process is called the main process

Create a Web page in the main process to display the user page. A ELECTRON has and only one main process

Electron uses Chromium to present Web pages, each page running in its own rendering process

Quick start

Next, let the code do the talking, the untouchable Hello World

Create a folder and execute NPM init -y to generate package.json file, download the Electron module and add development dependencies

mkdir electron_hello && cd electron_hello && npm init -y && npm i electron -D
Copy the code

If the download speed is too slow or fails, use CNPM. The installation method is as follows

# download CNPM
npm install -g cnpm --registry=https://registry.npm.taobao.org
# download electron
cnpm i electron -D
Copy the code

Create index.js and write the following

const {app, BrowserWindow} = require('electron')

// Create global variables and reference them below to avoid GC
let win

function createWindow () {
    // Create a browser window and set the width and height
    win = new BrowserWindow({ width: 800.height: 600 })
    
    // Load the page
    win.loadFile('./index.html')
    
    // Open the developer tool
    win.webContents.openDevTools()
    
    // Add the window closing event
    
    win.on('closed', () => {
        win = null  // Cancel the reference})}// Call the function after initialization
app.on('ready', createWindow)  

Exit when all Windows are closed.
app.on('window-all-closed', () = > {// On macOS, unless the user explicitly exits with Cmd + Q,
   // Otherwise, most apps and their menu bar remain active.
   if(process.platform ! = ='darwin') {
        app.quit()
   }
})
  
app.on('activate', () = > {// On macOS, when you click the Dock icon and no other Windows open,
// Usually a window is recreated in the application.
    if (win === null) {
      createWindow()
    }
})
Copy the code

Create index. HTML


      
<html>
    <head>
      <meta charset="UTF-8">
      <title>Hello World!</title>
    </head>
    <body>
        <h1 id="h1">Hello World!</h1>
        We are using node
        <script>
            document.write(process.versions.node)
        </script>
        Chrome
        <script>
            document.write(process.versions.chrome)
        </script>,
        and Electron
        <script>
            document.write(process.versions.electron)
        </script>
    </body>
</html>
Copy the code

Finally, modify the main field in packge.json and add the start command

{... main:'index.js'.scripts: {"start": "electron ."}}Copy the code

After executing NPM run start, our application will pop up.

debugging

We know that Electron has two processes, the main process and the renderer process. How do we debug them during development? The old lady eats persimmon, let’s pick the soft one

Rendering process

BrowserWindow is used to create and control the BrowserWindow by calling the API on its instance

win = new BrowserWindow({width: 800.height: 600})
win.webContents.openDevTools() // Enable debugging
Copy the code

Debugging up and Chrome is the same, do not want to be so sour cool

The main process

Use VSCode for debugging

Open the project with VSCode and click the debug button

Click the debug drop-down box

Select Add Configuration, select Node

The default debug configuration is turned on, which looks something like this

What? Yours is not, if not, just copy the following and replace your configuration

Configurations. If you want to do that, copy the second item in configurations into your Configurations. The first configuration is used to debug node

{
  "version": "0.2.0"."configurations": [{"type": "node"."request": "launch"."name": "Start program"."program": "${workspaceFolder}/main.js"
    },
    {
        "name": "Debug Main Process"."type": "node"."request": "launch"."cwd": "${workspaceFolder}"."runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron"."windows": {
          "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
        },
        "args" : ["."]]}}Copy the code

You can see ${workspaceFolder}, which is a variable about VSCode that represents the path of the currently open folder

Please click here for more variables

After modifying the configuration, we debug the panel and select what we just configured

Mark where you need to debug in your code, and then click on the green triangle

Process of communication

In Electron, GUI-related modules (dialog, Menu, etc.) are only available in the main process, not in the renderer process. In order to use them in the renderer process, the IPC module is required to send interprocess messages to the main process. The following describes several methods of interprocess communication.

Elder brother good

IpcMain and ipcRenderer are two good gay friends, through these two modules can realize the process of communication.

  • IpcMain is used in the main process to process synchronous and asynchronous information sent by the renderer process (web page)

  • IpcRenderer is used in the renderer process to send synchronous or asynchronous messages to the main process, and can also be used to receive replies from the main process.

The communication of the above two modules can be understood as publish-subscribe mode. Next, let’s see how they are used

The main process

const {ipcMain} = require('electron')

// Listen for events from the renderer
ipcMain.on('something', (event, data) => {
    event.sender.send('something1'.'I'm the value returned by the main process')})Copy the code

Rendering process

const { ipcRenderer} = require('electron') 

// Send events to the main process
ipcRenderer.send('something'.'Value transferred to main process')  

// Listen for events from the main process
ipcRenderer.on('something1', (event, data) => {
    console.log(data) // I am the value returned by the main process
})
Copy the code

The above code uses asynchronous transmission of messages. Electron also provides an API for synchronous transmission.

Sending synchronous messages will block the entire rendering process and you should avoid using this method – unless you know what you are doing.

Don’t use IPC to transfer large amounts of data. It can cause performance problems and even make your entire application get stuck.

Remote module

With the remote module, you can call methods on the main process object without having to explicitly send interprocess messages.

const { dialog } = require('electron').remote
dialog.showMessageBox({type: 'info'.message: 'Module that uses the main process directly in the renderer process'})
Copy the code

webContents

WebContents, which renders and controls the web page, is a property of the BrowserWindow object, and we use the Send method to send an asynchronous message to the renderer process.

The main process

const {app, BrowserWindow} = require('electron')

let win

app.on('ready', () => {

    win = new BrowserWindow({width: 800.height: 600})
    
    // Load the page
    win.loadURL('./index.html')
    
    // Triggered when navigation is complete, i.e. the TAB's spinner will stop spinning and assign the onload event.
    win.webContents.on('did-finish-load', () = > {// Send data to the renderer
        win.webContents.send('something'.'Data sent by the main process to the renderer')})})Copy the code

Rendering process


      
<html>
    <head>
    </head>
    <body>
        <script>
            require('electron').ipcRenderer.on('something', (event, message) => {
                console.log(message) // The data that the main process sends to the renderer
            })
        </script>
    </body>
</html>
Copy the code

Renderer data sharing

In more cases, we use HTML5 API implementation, such as localStorage, sessionStorage, etc., and can also use ELECTRON IPC mechanism to implement

The main process

global.sharedObject = {
    someProperty: 'default value'
}
Copy the code

Rendering process

First page

require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'
Copy the code

Second page

console.log(require('electron').remote.getGlobal('sharedObject').someProperty) // new value
Copy the code

conclusion

The above four methods can realize the communication between the main process and the renderer process. It can be found that using the remote module is the simplest, and the renderer process code can directly use the ELECTRON module

Commonly used modules

Shortcut keys and menus

Local shortcut keys

Only triggered when focusing is applied, the main code is as follows

Official documentation has no effect on the test

const { Menu, MenuItem } = require('electron')
const menu = new Menu()
  
menu.append(new MenuItem({
  label: 'Custom shortcut keys'.submenu: [{label: 'test'.accelerator: 'CmdOrCtrl+P'.click: (a)= > { 
          console.log('I'm a local shortcut')
      }
    }
  ]
}))
Menu.setApplicationMenu(menu)
Copy the code

Global shortcut key

Global registration, regardless of whether the application is focused or not, is triggered. Use globalShortcut to register with the main code as follows,

const {globalShortcut, dialog} = require('electron')

app.on('read', () => {
    globalShortcut.register('CmdOrCtrl+1', () => {
        dialog.showMessageBox({
            type: 'info'.message: 'You pressed the global register shortcut.'})})})Copy the code

The dialog module is used as shown below

Context menu

The context menu is the menu that is displayed when we right-click, and is set in the renderer process

The main code is as follows

const remote = require('electron').remote;  // A module that can only be used by the main program through the remote module
const Menu = remote.Menu;
const MenuItem = remote.MenuItem;
var menu = new Menu();
menu.append(new MenuItem({ label: 'MenuItem1'.click: function() { console.log('item 1 clicked'); }})); menu.append(new MenuItem({ type: 'separator' }));
menu.append(new MenuItem({ label: 'MenuItem2'.type: 'checkbox'.checked: true }));

window.addEventListener('contextmenu', (e) => {
  e.preventDefault();
  menu.popup(remote.getCurrentWindow());
}, false);
Copy the code

The application menu

Above we created a local shortcut key through the Menu module, the application Menu is also used by the Menu module, we see that looks like the same, in fact, the implementation is similar, we use here to create a template to achieve, the main code is as follows:

const {app, Menu} = require('electron')
const template = [
  {
    label: 'operation'.submenu: [{
        label: 'copy'.accelerator: 'CmdOrCtrl+C'.role: 'copy'
    }, {
        label: 'paste'.accelerator: 'CmdOrCtrl+V'.role: 'paste'
    }, {
        label: 'reload'.accelerator: 'CmdOrCtrl+R'.click: function (item, focusedWindow) {
            if (focusedWindow) {
                // on reload, start fresh and close any old
                // open secondary windows
                if (focusedWindow.id === 1) {
                    BrowserWindow.getAllWindows().forEach(function (win) {
                        if (win.id > 1) {
                            win.close()
                        }
                    })
                }
                focusedWindow.reload()
            }
        }
    }]
  },
  {
    label: 'Load web page'.submenu: [{label: 'youku'.accelerator: 'CmdOrCtrl+P'.click: (a)= > { console.log('time to print stuff')}}, {type: 'separator'
      },
      {
        label: "Baidu",}]}]if (process.platform === 'darwin') {
    const name = electron.app.getName()
    template.unshift({
      label: name,
      submenu: [{
        label: ` about${name}`.role: 'about'
      }, {
        type: 'separator'
      }, {
        label: 'service'.role: 'services'.submenu: []}, {type: 'separator'
      }, {
        label: Hidden `${name}`.accelerator: 'Command+H'.role: 'hide'
      }, {
        label: 'Hide the other'.accelerator: 'Command+Alt+H'.role: 'hideothers'
      }, {
        label: 'Show all'.role: 'unhide'
      }, {
        type: 'separator'
      }, {
        label: 'exit'.accelerator: 'Command+Q'.click: function () {
          app.quit()
        }
      }]
    })
}

app.on('read', () = > {const menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
})

Copy the code

The system tray

The main code

const { app, Tray } = require('electron') 
/* omit other code */
let tray;
app.on('ready', () => {
    tray = new Tray(__dirname + '/build/icon.png');// System tray icon
    
    const contextMenu = Menu.buildFromTemplate([ / / the menu item
      {label: 'show'.type: 'radio'.click: (a)= > {win.show()}},
      {label: 'hide'.type: 'radio'.click: (a)= > {win.hide()}},
    ])
    
    // Tray. on('click', () => {// The mouse click event is best set with only one menu
    // win.isVisible() ? win.hide() : win.show()
    // })
    
    tray.setToolTip('This is my application.') // Mouse over the prompt
    
    tray.setContextMenu(contextMenu) // Apply the menu item
})

Copy the code

The module”

Menu

MenuItem

globalShortcut

dialog

tray

Open the page

shell

The main process opens the page and invokes the default browser to open the page, using the shell module

const { app,shell } = require('electron')

app.on('ready', () => {
    shell.openExternal('github.com')})Copy the code

The github page will be opened using the default browser once the app is launched

window.open

Used in the rendering process, the current application opens the page

window.open('github.com')
Copy the code

webview

Use webView to display external Web content in a separate frame and process

Use it directly in index.html

<webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>
Copy the code

The module”

shell

window.open

webview

QA

Other application modules and apis can be downloaded

Demo application

Demo application Chinese version

template

electron-forge

Electron forge contains templates for vue, React, Angular, and more out of the box.

npm i -g electron-forge
electron-forge init my-app template=react
cd my-app
npm run start 
Copy the code

The directory structure is as follows

.compilerc is the configuration file for electron-compile, similar to.babelrc

Electron -compile is a conversion rule that allows you to compile JS and CSS in your application

electron-react-boilerplate

If you don’t want any tools and want to simply build from a template, the React-electron template can take a look.

Electron -react- Boilerplate is a double package.json configuration project with the following directory

electron-vue

Electric-vue makes full use of vue-CLI as a scaffolding tool, plus webpack, electric-Packager, or electric-Builder with vue-Loader, and some of the most commonly used plug-ins, For example, vuE-Router and VUex.

The directory structure is as follows

Chinese tutorial

More templates

More templates are available here

packaging

How do we package our developed application as an.app or.exe executable file, and that involves an important part of packaging, which is using the electron quick-start project

At present, the mainstream packaging tools have two electric-packager and electric-Builder

You need to download Wine to pack the Windows installation package for Mac

brew install wine

If any component is missing, download it according to the error message

electron-packager

Electron packager packs your electron into runnable files (.app,.exe, etc)

Run the NPM I electron-packager -d command to install the package

Electron -packager. Quick pack

Packaging,

electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --out=out --icon=assets/app.ico --asar --overwrite --ignore=.git
Copy the code
  • Sourcedir Project entry directory according to package.json
  • Appname package name
  • Platform Construction Platform includesdarwin, linux, mas, win32 all
  • The ARCH build architecture containsia32,x64,armv7l,arm64
  • Out The address after packing
  • Icon Package icon
  • Asar generates app.asar, or its own source code
  • Overwrite overwrites the last package
  • Ignore files that are not packaged

The first time you pack a package that requires a binary download will take a little longer, and the cache will be much faster later.

The package directory is

The electron-quick-start can be directly opened and run

Cache address

  • Mac ~/Library/Caches/electron/
  • Windows $LOCALAPPDATA/electron/Cache or ~/AppData/Local/electron/Cache/
  • Linux $XDG_CACHE_HOME or ~/.cache/electron/

electron-builder

Electron Builder is a complete solution to pack and build the Electron App for MacOS, Windows and Linux. It also provides “automatic update” support out of the box

NPM I electron- Builder-d download

Electron – builder package

In the following

Also, it will take a long time to pack for the first time. Don’t worry, wait for good news.

Will be packaged in the dist directory by default, including the following

MAC files have runtime files that are packaged using ASAR by default

The electron-builder –dir will only generate package files, useful for testing

Pit craters

The first time when packing will be slow, if you and I hand out directly, when packing again, congratulations, mistake. The error message is as follows

• electron - builder version =20.282.
  • loaded configuration file=package.json ("build"Field • Description is missedin the package.json appPackageFile=/Users/Shisan/Documents/self/you - app/package. The json, writing effective config file = dist/builder - effective - config. Yaml, no Native production Dependencies • Packaging platform= Darwin arch= X64 electron=2.07.AppOutDir = Dist/MAC • Cannot unpack the electron zip file, will be re-downloaded error=zip: not a valid zip file ⨯ zip: not a valid zip fileError: /Users/shisan/Documents/self/you-app/node_modules/app-builder-bin/mac/app-builder exited with code 1
    at ChildProcess.childProcess.once.code (/Users/shisan/Documents/self/you-app/node_modules/builder-util/src/util.ts:254:14)
    at Object.onceWrapper (events.js:272:13)
    at ChildProcess.emit (events.js:180:13)
    at maybeClose (internal/child_process.js:936:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:220:5)
From previous event:
    at unpack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/out/electron/ElectronFramework.js:191:18)
    at Object.prepareApplicationStageDirectory (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/electron/ElectronFramework.ts:148:50)
    at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/platformPackager.ts:179:21at Generator.next (<anonymous>) From previous event: at MacPackager.doPack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/platformPackager.ts:166:165) at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/macPackager.ts:88:63 at Generator.next (<anonymous>) From previous event: at MacPackager.pack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/macPackager.ts:80:95) at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:376:24 at Generator.next (<anonymous>)  at xfs.stat (/Users/shisan/Documents/self/you-app/node_modules/fs-extra-p/node_modules/fs-extra/lib/mkdirs/mkdirs.js:56:16) at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/polyfills.js:287:18 at FSReqWrap.oncomplete (fs.js:171:5) From previous event: at Packager.doBuild (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:344:39) at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:314:57 at Generator.next (<anonymous>)  at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/graceful-fs.js:99:16 at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/graceful-fs.js:43:10 at FSReqWrap.oncomplete (fs.js:153:20) From previous event: at Packager._build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:285:133) at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:281:23 at Generator.next (<anonymous>)  From previous event: at Packager.build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:238:14) at build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/index.ts:58:28) at build (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/builder.ts:227:10) at then (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:42:48) at runCallback (timers.js:763:18) at tryOnImmediate (timers.js:734:5) at processImmediate (timers.js:716:5) From previous event: at Object.args [as handler] (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:42:48) at  Object.runCommand (/Users/shisan/Documents/self/you-app/node_modules/yargs/lib/command.js:237:44) at Object.parseArgs [as _parseArgs] (/Users/shisan/Documents/self/you-app/node_modules/yargs/yargs.js:1085:24) at Object.get [as argv] (/Users/shisan/Documents/self/you-app/node_modules/yargs/yargs.js:1000:21) at Object.<anonymous> (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:25:28) at Module._compile (internal/modules/cjs/loader.js:654:30) at Object.Module._extensions.. js (internal/modules/cjs/loader.js:665:10) at Module.load (internal/modules/cjs/loader.js:566:32) at tryModuleLoad (internal/modules/cjs/loader.js:506:12) at Function.Module._load (internal/modules/cjs/loader.js:498:3) at Function.Module.runMain (internal/modules/cjs/loader.js:695:10) at startup (internal/bootstrap/node.js:201:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3) npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! [email protected] dist: 'electric-Builder -- MAC -- X64' NPM ERR! Exit status 1 npm ERR! npm ERR! Failed at the [email protected] dist script.npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /Users/shisan/.npm/_logs/ 2018-08-22t06_28_55_102z-debug. Log * Error building interactive interfaceCopy the code

The problem is in the download. Zip, interrupted operation, all performed after packaging, can’t find the file (or incomplete documents) is an error, need to clear the cache manually Cache path in ~ / Library/Caches/electron /

Commonly used parameters

The electron builder configuration file is written in the Build field in package.json

Directories: {"build": {"appId": "com.example.app", // App directories: {"buildResources": "Build ", // Build resource path defaults to build" output": "dist" // Output directory defaults to dist}," MAC ": {"category": "Public. App-category. Developer-tools ", // Application category "target": [" DMG ", "zip"], // Target package type "icon": "Build /icon.icns" // icon path}," DMG ": {"background": "Build /background.tiff or build/background. PNG ", // background image path "title": "title", "icon": "build/icon.icns" // icon path}, "win": {"target": ["nsis","zip"] // Target type}}Copy the code

Application category

More parameters

There is no need for ASAR manual packaging by using the electric-package or electric-Builder. These two tools have been integrated into the package. The following content is just for understanding

asar

Introduction to the

Asar is a tar-like archive format that combines multiple files into a single file. Electron can read any file contents from it without decompressing the entire file.

use

As we have seen above, we can add the — ASar parameter when using electron package. This parameter is used to package our source code into ASAR format, otherwise it will be our source code.

The electron-quick-start template is still used, and the electron-package is used for packaging

After the package is packaged, right-click the application directory to display the package content

Go to Contents -> Resources -> app

You can see our original file

Use the electron-package. –asar to pack and check again that the source files in your app have been packed as ASAR files

Common commands

  • packaging
asar pack|p <dir> <ouput>
Copy the code

Such as asar. / app. Asar

  • Unpack the
asar extract|e <archive> <output>
Copy the code

Such as asar e app.asar./

In fact, even with asAR packaging, our source code is still exposed, can be easily decrypted with ASAR decompression, and is king with WebPack to compress and obturate the code.

Automatic updates

We use electron builder and electron updater to automatically update our applications, not the autoUpdater in Electron

process

Create a certificate

Regardless of which method is used for automatic updates, code signing is essential, and we used to create a local certificate to test automatic updates

Find keystring access in others

Choose Keychain Access -> Certificate Assistant -> Create Certificate to create a new certificate

Give a loud name, select code signature for the certificate type, and click Create

Find it in the keychain after it is created

Right-click and select Change Trust Settings to set trust to always trust

Code signing

  • No code signature

  • Code signing

Setting environment Variables

Run sudo vi ~/.bash_profile to add variables

export CSC_NAME="electron_update"
Copy the code

Run source ~/.bash_profile to reload the variable file

Run echo $CSC_NAME to check whether the variable takes effect. If it does not, run the preceding command to reload the file

If the variable is still unavailable after multiple reloading, exit the terminal directly and log in to the terminal again

Packaging code

Use electric-Builder for packaging and electric-quick-start for projects

Let’s start by adding the packaged build configuration in package.json

"build": { "appId": "org.electron.com", "publish": [ { "provider": "generic", "url": "Http://172.28.86.36:8080/"}], "productName" : "my", "directories" : {" output ":" dist "}, "MAC" : {" target ": [ "dmg", "zip" ] }, "win": { "target": [ "nsis", "zip" ] }, "dmg": { "backgroundColor": "red", "title": "made", "contents": [ { "x": 400, "y": 128, "type": "link", "path": "/Applications" } ] } }Copy the code

In the build field, we added the Publish field, which is configured to update automatically, and the URL is the server address.

The server is available to ushttp-serverModule, quickly build a static server

After performing packaging, output

Take a look at the latest-mac.yml file

You can see the Version field, which indicates the current version of the application. Where did this field come from?

That’s the version field in our package.json file

Automatic updates

Write the following code in the main process

const {app, BrowserWindow, ipcMain} = require('electron')

const { autoUpdater } = require('electron-updater')

// Address of the local server
const feedURL = ` http://172.28.82.40:8080/ `

let mainWindow

function createWindow () { // Create window
  mainWindow = new BrowserWindow({width: 800.height: 600})
  mainWindow.loadFile('index.html')

  mainWindow.on('closed'.function () {
    mainWindow = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed'.function () {
  if(process.platform ! = ='darwin') {
    app.quit()
  }
})

app.on('activate'.function () {
  if (mainWindow === null) {
    createWindow()
  }
})

// Listen for custom update events
ipcMain.on('update', (e, arg) => {
  checkForUpdate()
})

const checkForUpdate = (a)= > {
  // Set the url to check for updates and initiate automatic updates
  autoUpdater.setFeedURL(feedURL)

 // Listening error
  autoUpdater.on('error', message => {
    sendUpdateMessage('err', message)
  })
 // Triggered when checking for updates
  autoUpdater.on('checking-for-update', message => {
    sendUpdateMessage('checking-for-update', message);
  })
 // 
  autoUpdater.on('download-progress'.function(progressObj) {
    sendUpdateMessage('downloadProgress', progressObj);
  });
  // Update the download completion event
  autoUpdater.on('update-downloaded'.function(event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
      
      ipcMain.on('updateNow', (e, arg) => {
          autoUpdater.quitAndInstall();
      });
      sendUpdateMessage('isUpdateNow');
  });
 // Check with the server to see if any updates are available now
  autoUpdater.checkForUpdates();
}

// Sending a message triggers the message event
function sendUpdateMessage(message, data) {
  mainWindow.webContents.send('message', { message, data });
}
Copy the code

Then change our renderer code

const {ipcRenderer} = require ('electron');
const button = document.querySelector('#button')


const ul = document.querySelector('ul')
button.onclick = (a)= > {
  ipcRenderer.send('update')
}

ipcRenderer.on('message', (event, {message,data }) => {
  let li = document.createElement('li')
  li.innerHTML = message + " <br>data:" + JSON.stringify(data) +"<hr>";
  ul.appendChild(li)
  if (message === 'isUpdateNow') {
    if (confirm('Update now? ')) {
        ipcRenderer.send('updateNow'); }}})Copy the code

Page code


      
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <h1>The current version is 1.0.3</h1>

    <ul>
      <li>Life cycle process display</li>
    </ul>

    <button id="button">Click on the I</button>
    <script>
      // You can also require other files to run in this process
      require('./renderer.js')
    </script>
  </body>
</html>
Copy the code

The update action is triggered by a button click event.

Package it and install the 1.0.3 version.

Then change the version field in the package.json file to 1.0.5 and the index.html field to 1.0.5 to package.

Create a folder anywhere, such as test

Move the packaged file to test and run http-server./ to set up the service

When we click the button, we can update the application, as shown below

Click OK, wait for a moment, and then open the latest version of the app

That completes the automatic update of ELECTRON.

The last

All the code in this article can be found at Github

OCR related demo borrows (Chao) from (XI) Jartto’s electron- OCR, which is linked below.

reference

Summary of common parameters of the electron-packager command

Electron package Mac installation package code signature problem solution

Uncle Sunan’s electron

electron-ocr

The signature mentioned in this article must be purchased with an Apple developer account.