Mogujie front end team officially settled in nuggets, hope you don’t be stingy with your hands of Praise (bixin)!

Zero, introduce

We will issue a series of Electron. This article mainly introduces basic things related to Electron. In the follow-up, we will introduce more skills and solutions to problems in actual combat.

This paper mainly includes:

  1. Introduction of Electron
  2. Quick start
  3. process
  4. packaging
  5. Summary on pit

A,ElectronIntroduction to the

Electron is a cross-platform development framework for empowering front ends, allowing developers to build cross-platform desktop applications using front-end technologies such as JavaScript, HTML, and CSS. Electron does this by merging Chromium and Node.js into the same runtime environment and packaging it as an application for Mac, Windows, and Linux, leaving developers to focus on the front-end code.

Quick start Electron + React

Electron provides a project named electron-quick-start, which can be cloned and used as a template. In this paper, create-React-app is used to learn step by step.

Create a React project

Install create-react-app
npm install -g create-react-app

Create the electron-react project
create-react-app electron-react

# Start a project
cd electron-react && npm start
Copy the code

Open the browser to localhost:3000 and the following screen appears:

Configuring the electron Environment

Create a new index.html folder under “public” and write something like this:

.<div>hello world</div>.Copy the code

Next, create the electron main thread file, public/main.js, under the public path is recommended.

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

Finally, modify the path corresponding to the main field in package.json and add the start command

{... "main": "main.js", "scripts": "electron ." }Copy the code

If you run NPM start, the following screen will appear:

Here I have written a simple page, you can also write about their own interests.

So, a simple desktop application is developed, really so easy.

Three, processes,

The electron process is divided into the main process and the render process

Main process & renderer process

Let’s start with the basic directory structure for the Electron project

App └ ─ public └ ─ index. The HTML -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the entry file ├ ─ main. Js -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the program start entrance, Main process ├ ─ the ipc -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- process module between ├ ─ appNetwork -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- application communication module └ ─ SRC -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - window management, Rendering process ├ ─ components -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- a common component module ├ ─ store -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- data sharing module ├ ─ the statics -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- static resource module └ ─ pages -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- window business module ├ ─ window A -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- window └ ─ window B -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - the windowCopy the code

The process of the file corresponding to the main field in package.json is the main process. Electron integrates Chromium to display the window interface, and the content seen in the window is rendered in HTML. Chromium itself is a multi-process rendering architecture (by default, Chromium’s default policy is to start a new process for each TAB to ensure that each page is independent and non-intrusive. Avoid the crash of one page and render all pages unusable), so Electron will also use Chromium’s multi-process architecture when displaying the window. This multi-process rendering architecture is called the render process in Electron.

Interprocess communication

In ELECTRON, GUI-related modules (such as Dialog, Menu, etc.) are only available in the main process, not in the renderer process. To use them in the renderer process, you need to use the IPC module to send messages to the main process. Here are a few ways to communicate between processes.

  1. ipcMain & ipcRenderer

Asynchronous communication from the main process to the renderer, and messages can also be sent from the main process to the renderer, see webcontents.send.

When a message is sent, the event name is channel.

To reply to a synchronization message, set event.returnValue.

To send an asynchronous message back to the sender, use event.reply(…) This helper method will automatically process messages from the renderer, whereas event.sender.send(…) This method always sends the message to the main process.

Here is an example of sending and processing messages between rendering and the main process:

// In the main process
const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
    console.log(arg); / / output 'ping'
    event.reply('asynchronous-reply'.'pong');
})

ipcMain.on('synchronous-message', (event, arg) => {
    console.log(arg) / / output 'ping'
    event.returnValue = 'pong'
})
Copy the code
// In the render process
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message'.'ping')) / / output 'pong'

ipcRenderer.on('asynchronous-reply', (event, arg) => {
    console.log(arg); / / output 'pong'
})

ipcRenderer.send('asynchronous-message'.'ping')
Copy the code
  1. Remote module

Remote provides an easy way for the renderer to communicate with the main process. You can call methods on the main process object without having to explicitly send interprocess messages. Example: Create a browser window from a renderer

const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({ width: 800.height: 600 })
win.loadUrl('https://www.mogu.com')
Copy the code

Note that, in turn, if you need to access from the main process rendering process), you can use webContents. ExecuteJavascript.

  1. webContents

Send an asynchronous message to the renderer process via a channel, which can send arbitrary parameters. Internally, parameters are serialized to JSON, so the function and prototype chains of parameter objects are not sent

In addition to these methods, you can also use localStorage, sessionStorage, etc.

Four, packaging,

After development, we still need to package the application into an executable file, which is the most difficult part of learning electron until now.

At present, the mainstream packaging tools include electron- Packager and electron- Builder

electron-packager

Install dependencies:

npm i electron-packager --save-dev

Packaging:

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

You can also run NPM run electronic-packager directly. Packaging.

electron-builder

Official explanation:

A complete solution to package and build a ready for distribution Electron, Proton Native or Muon app for macOS, Windows and Linux with Auto Update support out of the box.

In short, electric-Builder has more features than electric-Packager, supports more platforms, and also supports automatic updates. In addition to these points, the autograph-Builder prints a lighter package and can package a Setup installer without exposing the source code. Plus it feels a little less cratered than the electron packager.

Install dependencies:

npm i electron-builder --save-dev

Copy the code

Packaging:

  • In the projectpackage.jsonFile definitionbuildfield
{
    "build": {
        "appId": "com.xxx.app"."extends": null."files": [
            "build/**/*"]."mac": {
            "icon": "icons/icon.icns"
        },
        "win": {
            "target": "nsis"."icon": "icons/icon.png"}}}Copy the code

This is the most basic configuration, of course, there may be other issues during the packaging process that need to be modified configuration. In general, it is not enough to write a build folder in a Files configuration. Add additional paths depending on the project structure and packaging.

  • Add scripts command
{
    "scripts": {
        "pack": "electron-builder"
    }
}

Copy the code
  • Run NPM Run Pack to pack

After the packaging is complete, there is an executable file in the dist directory. If no error is reported after opening the file, it indicates that the packaging is successful.

Five, step pit summary

Most of them are potholes

  • Error when using electron-packager for packing

Generated checksum for “electron- v6.0.2-Darwin -x64.zip” did not match expected checksum. Upgrade to a Node version higher than 8.x.

  • Error opening package generated executable file

There may be several reasons for this problem:

  1. There may be direct access to the local path in the project, which the browser does not allow for security reasons.
  2. Json build configuration issues, if main.js is in a deep path, need to add a separate main.js path below
"build": {
    ...
+ "public/main.js". }Copy the code
  1. The path in the Webpack configuration uses __dirname directly, which can be obtained using the getAppPath method of the remote module
const remote = require('remote')
const app = remote.require('app')
console.log(app.getAppPath());

Copy the code

Reference github.com/electron/el…

  • dependencies & devDependencies

When packing electron, it is important to distinguish between production and development environment dependencies. Avoid this type of error:

  • About slow packing: NPM & CNPM

Node_modules CNPM installs various node_modules. In this way, all packages are installed flat, and node_modules expands with a lot of files all at once, resulting in a very slow packaging process. But if node_modules is installed using NPM, all packages are in a tree structure, with a deeper hierarchy. But the packing will be much faster. For details, see: Can’t the electron packing be finished after 2 hours?

Recommend the article

  1. Iweiyun. Making. IO / 2019/01/04 /…

Refer to the article

  1. Nodejs.org/api/addons….