If you want to try electron, why don’t you take a look at this climbing pit summary

Time:2020-10-19

preface

The web side can do a lot of things, but when it comes to the operating system, it may be a little inadequate. Some time ago in the development of a web system, we encountered a similar situation. We need to get some information about the computer’s operating system, such as MAC address. Our web system is completely placed on the server, through the browser to run, but through the web can not directly achieve the desired effect.

The problem is left to people. After the discussion among colleagues, because the system itself is not complex, and to carry out rapid development. We decided to use the page of electron + original web system to solve the problem of operating system information.

This article summarizes some of the problems and solutions I encountered when using electron.

What is electron?

Building cross platform desktop applications using JavaScript, HTML and CSSElectronIntroduction to the official website

Electron is an open source framework developed by GitHub. It allows the use of Node.js (as the back-end) and chromium (as the front-end) to complete the development of desktop GUI applications. Electron has been used in front-end and back-end development by many open-source Web applications, including atom of GitHub and visual studio code of Microsoft. ——Know

It can be simply understood that electron has set up a web project Node.js Environment, so that we can call Node.js The rich API of. In this way, we can use JavaScript to write desktop applications and expand a lot of things we can’t do on the web.

How to build electron application?

It’s easy to build an electron app, either by looking directly at official documents or by taking advantage of existing wheels. Basically, it can be divided into two categories: templates and command-line tools. These two ways have their own advantages, which way to choose should be based on the actual situation. Take me for example, because the project I’m going to do already has a web page, and these templates are basically not applicable. In order to catch up with the schedule, I directly refer to the official website——Build your first electronic appAdd the original code to build the project.

Here are some common build templates and command-line tools

Template

Command line tools

An example

The following is the most basic electron project, and the subsequent codes are expanded on this basis.

npm install --save-dev electron

General structure

demo/
├── package.json
├── main.js
└── index.html

package.json

{
  "name": "demo",
  "version": "1.0.0",
  "description": "electornDemo",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "author": "xmanlin",
  "license": "MIT",
  "devDependencies": {
    "electron": "^9.0.0"
  }
}

main.js

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

app.on('ready', function createWindow () {
    //You can create multiple rendering processes
    let win = new BrowserWindow({
        width: 800,
        height: 600,
    })
    
    win.show()

    //Web pages in the rendering process can load local files
    win.loadFile('index.html')


    //Remember to clear the variable after the page is closed to prevent memory leaks
    win.on('closed', function () {
        win = null
    })


})

//Close the main process after all the pages are closed. Different platforms may have different processing methods
app.on('window-all-closed', () => {
    app.quit()
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>demo</title>
</head>
<body>
    < div > an electronic project < / div >
    <script>
    
    </script>
</body>
</html>

What are the main process and rendering process?

In electron, the concepts of main process and rendering process are very important. For details, please refer to the introduction on the official website:Main process and rendering process

Main process

  • functionpackage.jsonMediummainThe process of the script is the main process.
  • An electronic application has and only one main process.
  • The main process can perform GUI related native API operations.

Rendering Progress

  • Electron uses chromium to display web pages, so chromium’s multiprocessing architecture is also used.
  • Each web page runs in its own rendering process.
  • useBrowserWindowClass starts a rendering process and runs the instance in the processBrowserWindowAfter the instance is destroyed, the corresponding rendering process is terminated.
  • Native resources cannot be called during the rendering process, but they are also included in the rendering process Node.js Environment, so it can be introduced Node.js

Module, in Node.js Supported, you can interact with the operating system on the page.

How to call during the rendering process Node.js API?

After electron 5.0, the rendering process cannot be called by default Node.js After setting, you can:

Main process( main.js )

let win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
        NodeIntegration: true, // set to true can be invoked in this rendering process. Node.js
    }
})

How to open developer tools?

Although electron uses chromium, it is not like a browser to open the developer tool, such as pressing F12 by default in windows.

There are two ways to open developer tools in electron:

The first is to set it in the main process. After setting, start the project, and the developer tool will be opened by default in the rendering process

 win.webContents.openDevTools();

Second, you can select View > toggle developer tools from the menu bar of the rendering process window. (or directly follow the shortcut key above)

The problem of printing garbled code on the electronic console?

We may have a Chinese garbled problem in the windows console. When we enter CHCP in the windows console, we can see the current character encoding. The common value of GB2312 is 936, and the value of utf8 is 65001. In this case, as long aspackage.jsonIt can be solved by setting.

"start": "chcp 65001 && electron ."

How does the main process communicate with the rendering process?

Between the main process and the rendering process, theipcRendererandipcMainModule communication.

The main process actively sends messages to the rendering process

Main process( main.js )

//The main process sends a message to the rendering process, 'did finish load': when the navigation is completed, the onload event is completed
win.webContents.on('did-finish-load', () => {
    win.webContents.send ('msg ','message from main process')
})

Rendering process( index.html )

<script>
    const {ipcRenderer} = require('electron')
    ipcRenderer.on('msg', (event, message) => {
        console.log (message) // the message comes from the main process
    })
</script>

The rendering process actively sends messages to the main process

Rendering process( index.html )

const {ipcRenderer} = require('electron')
ipcRenderer.send ('indexmsg ','message from rendering process')

Main process( main.js )

const {ipcMain} = require('electron')
ipcMain.on('indexMsg',(event,msg) => {
    console.log (MSG) // message from rendering process
})

How do rendering processes communicate with each other?

There are many ways to communicate between rendering processes. Here are a few:

Use global share properties

//Main process
global.sharedObject = {
  user: ''
}

//Rendering process one
const {remote} = require('electron')
remote.getGlobal('sharedObject').user = 'xmanlin'

//Rendering process 2
const {remote} = require('electron')
console.log(remote.getGlobal('sharedObject').user) //xmanlin

ipcRenderer.sendTo()

Here isipcRenderer.sendTo()Parameters of

ipcRenderer.sendTo(webContentsId, channel, [, arg1][, arg2][, ...])
ipcRenderer.sendTo(windowId, 'ping', 'someThing')
//webContentsId : Number
//channel : String
//...args : any[]

Specific usage

Main process( main.js )

//Create a new rendering process
let win2 =  new BrowserWindow({
    width: 800,
    height: 600,
})

//Sets a unique ID for the rendering process
win2.id = 2

Rendering process 1

<script>
    const {ipcRenderer} = require('electron')
    //Send a message to the rendering process with ID 2
    ipcRenderer.sendTo (2, 'MSG1','message from rendering process 1 ')
</script>

Rendering process 2

<script>
    const {ipcRenderer} = require('electron')
    ipcRenderer.on('msg1', (event, message) => {
        console.log (message) // message from rendering process 1
    })
</script>

Using main process as message transfer station

//Main process
ipcMain.on('msg1', (event, message) => {
  yourWindow.webContents.send('msg2', message);
}

//Rendering process 1
ipcRenderer.send ('msg1 ','message from rendering process 1')

//Rendering process 2
ipcRenderer.on('msg2', (event, message) => {
    console.log (message) // message from rendering process 1
  }
)

How to package a project?

Packaging is also an essential step. Here are two mature packaging tools:electron-packagerandelectron-builder。 These two tools are mainly used to configure them.

electron-packager

We can use electronic packer to package our existing electronic applications as exe executable files.

Install first

npm install electron-packager --save-dev

After installation, configure the basic command of electronic packer. The following is the basic format in the official document:

electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]

Briefly introduce the meaning of each parameter

  • Sourcedir: the path of the project
  • AppName: application name (the name of the packaged file)
  • Platform: an application that determines which platform you want to build (windows, MAC or Linux)

    • platform=win32For windows
    • platform=darwinFor Mac
    • platform=linux For Linux
  • Arch: decide whether to use x86 or x64 or both architectures
  • Optional options: optional options

The following is an example for reference

package.json

"scripts": {
    "build32": "electron-packager ./ appDemo --platform=win32 --arch=ia32  --out=./app --app-version=1.0.0 --overwrite --icon=./favicon.ico",
    "build64": "electron-packager ./ appDemo --platform=win32 --arch=x64  --out=./app --app-version=1.0.0 --overwrite --icon=./favicon.ico"
  }

The above are all packaged software under windows, with 32-bit for build32 and 64 bit for build64. In addition to the basic parameters, the meanings of the above parameters are as follows:

  • –Out indicates the directory of the files generated after packaging
  • –App version indicates the version number of the package makefile
  • –Rewrite means to delete the original package file and generate a new package file
  • Icon represents the icon for the packaged file

electron-builder

Electronic builder can not only be packaged as exe executable files, but also as installable programs. Compared with electronic packer, electronic builder has more functions.

The official website even more highly recommends yarn for installation

yarn add electron-builder --dev

Of course, NPM is OK

npm install electron-builder --save-dev

Then we can configure it

"scripts": {
  "pack": "electron-builder --dir",
  "dist": "electron-builder"
},
 "build": {
   "ProductName": "appdemo", // Chinese name of app
   "Appid": "appdemoid", // APP ID
   "Directories": {// output folder after packaging
     "buildResources": "resources",
     "output": "dist/"
   }
   "Files": [// source files that are still preserved after packaging
     "dist/electron",
     "node_modules/",
     "package.json"
   ],
   "Mac": {// Mac packaging configuration
     "target": "dmg",
     "icon": "icon.ico"
   },
   "Win": {// windows package configuration
     "target": "nsis",
     "icon": "icon.ico"
   },
   "DMG": {// DMG file packaging configuration "
     "artifactName": "appDemo.dmg",
     "contents": [
       {
         "type": "link",
         "path": "/Applications",
         "x": 410,
         "y": 150
       },
       {
         "type": "file",
         "x": 130,
         "y": 150
       }
     ]
   },
   "NSIS": {// NSIS file packaging configuration
     "oneClick": false,
     "Allowtochangeinstallationdirectory": true, // allows modifying the installation directory
     "Allowalelevation": true, // allows the request to be promoted. If false, the user must restart the installation program with elevated privileges.
     "installerIcon": "./build/icons/ aaa.ico ", // installation Icon
     "uninstallerIcon": "./build/icons/ bbb.ico ", // uninstall Icon
     "installerHeaderIcon": "./build/icons/ aaa.ico ", // header icon during installation
     "Create desktop shortcut": true, // create desktop icon
     "Createstartmenushortcut": true, // create start menu icon
     "Shortcutname": "XXX", // icon name
     "include": "build/script/ installer.nsh ", // contains a custom NSIS script, which is very useful for building a strict installation process.
   },
 }

Parameters can also be specified when packaging with electronic builder

--Mac, - m, - O, - MacOS Mac OS package
 --Linux, - L Linux package
 --Win, - W, - Windows Windows package
 --MWL is packaged for Mac OS, windows and Linux at the same time
 --X64 x64 (64 bit installation package)
 --IA32 IA32 (32-bit installation package)

All parameters can be referred toCommand Line Interface (CLI)

For NSIS, you can also learn about this packaging method:Electronic packer + NSIS

How to set the default window maximization and full screen?

Default maximize

//Main process( main.js )
let win = new BrowserWindow({show: false})
win.maximize()
win.show()

Default full screen

//Main process( main.js )
let win = new BrowserWindow({fullscreen: true})

How to customize the menu bar?

You can refer to this article directly-Custom menu using electronYou can also refer to the official documents directly. Of course, we can also hide our own menu bar and call the API for writing electron to write a menu bar. For example, this is what vscode does. Open vscode, and then find the switch developer tool in help. You may find a new world ~.

How to get mac address of operating system?

This is mainly called Node.js The MAC address of the system can be obtained.

var os=require("os");
//Get mac address
var mac = ''
var networkInterfaces=os.networkInterfaces();
for(var i in networkInterfaces){
    for(var j in networkInterfaces[i]){
        if(networkInterfaces[i][j]["family"]==="IPv4" && networkInterfaces[i][j]["mac"]!=="00:00:00:00:00:00" && networkInterfaces[i][j]["address"]!=="127.0.0.1"){
            mac = networkInterfaces[i][j]["mac"]
        }
    }
}

reference resources

https://www.electronjs.org/docs

https://blog.csdn.net/weixin_…

https://www.jianshu.com/p/62c…

https://blog.csdn.net/qq_3480…

https://segmentfault.com/a/11…

https://juejin.im/post/5cfd2e…

last

This article is about the problems I have encountered in learning and applying electron so far and the solutions I have found. I hope it will be helpful to you. If there are deficiencies or mistakes, please point out~