Author: Pug-Man-Littly

background

Taro IDE is a one-stop mobile development workbench that we are carefully building. In addition to realizing the full capabilities of Taro from project creation to preview and compilation, a series of processes including user testing, debugging and monitoring are also needed. To improve the development experience, a command-line tool is not enough. We need to develop a desktop client that provides Windows, MacOS, and other versions.

Electron was originally developed by Github as a desktop application framework for the Atom editor. Electron merges Chromium and Node into the same runtime environment, giving Web code the ability to interact with the underlying operating system and generate desktop applications for Windows, MacOS, Linux and other platforms when packaged. Compared with the native desktop application development framework, Electron is a little less powerful in terms of performance and application size. However, Electron supports the packaging of desktop applications from multiple platforms, and has been successful in the industry with integrated experience such as VSCode, Atom and Slack. We think Electron meets our needs perfectly.

Introduces Electron

If you just want to experience Electron, the fastest way to do it is to use Electron Fiddle, or just use scaffolding provided by the community.

Initially, Electron was attracted by the feature of “using a front-end technology stack to generate a multi-platform desktop application.” However, in subsequent development, it will be noticed that Electron has a more complex process model than Nw.js:

Electron’s architecture can be represented as follows:

In the Electron project, the process that runs the package.json main script is called the main process. The main process presents the user interface by creating web pages. These user interfaces run in separate rendering processes.

The Electron main process supports the Node API and can directly interact with the operating system at the bottom level, such as pop-up system notifications, file system reads and writes, and hardware device calls.

The Electron renderer process can only interact with its own Web content by default. The renderer can also have the ability to manipulate Node when nodeIntegration is turned on. The renderer also cannot directly operate the Dialog, system Notification, etc., which need to be invoked in the main process via the IPC/remote mechanism provided by Electron.

In the subsequent Electron upgrade, these constraints may also be adjusted for security and performance reasons. It can be said that the development experience of Electron is not very good, but it is the game between development experience and user experience that ensures the performance and security of Electron application.

Development workflow

We used the community-provided electronic-react-typescript as the initial scaffolding for the project. Reading package.json, we can see that the project uses WebPack to package the main and renderer processes, with SRC /main/main.ts as the entry point for the main process.

Electron’s BrowserWindow class creates and controls the BrowserWindow, while the app object controls the events and lifecycle of the application. The code for the main process looks like this:

import { app, BrowserWindow } from 'electron'

let win
app.on('ready', () => {
  win = new BrowserWindow({ width: 800, height: 600 });
  win.loadURL(`http://localhost:2003`);
  // xxx
});

app.on('activate', () => {})
app.on('window-all-closed', () = > {})Copy the code

The render process SRC /renderer/app. TSX is just a normal page, so I won’t go into details here. After installing the dependency, run yarn start-dev to start the project preview service.

The project uses WebPack to package the project code, which has two benefits. First, through Webpack processing, we can reduce the require call at runtime, which is helpful to the loading performance of Electron application. Second, with WebPack’s Tree shaking capability, unused code can be easily removed, reducing the size of the installation package.

To package the electron project, we need at least two WebPack configuration files, one to package the main process file, specifying target as electric-main, and another to package the render process, with target set to electric-renderer.

To assist in the commissioning of the Electron project, we can install Devtron. Devtron is a development debugging plug-in provided by Electron. After Devtron is added to the developer tools, IPC communications, project dependencies, events and other information can be viewed directly in the developer tools.

We can also install other developer tool extensions, such as Redux and React, if needed, by running them in the main process:

// main.js

const {
  default: installExtension,
  REACT_DEVELOPER_TOOLS,
  REACT_PERF,
  REDUX_DEVTOOLS
} = require('electron-devtools-installer')
const extensions = [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS, REACT_PERF]

extensions.forEach(extension => {
  try {
    installExtension(extension)
  } catch (e) {
    console.error(e)
  }
})
Copy the code

At this point, our development environment is set up and we can start developing business code.

To optimize the

Once the business code is developed, it’s time to optimize. Here mainly from the Electron application performance and volume of two aspects.

performance

Electron has been criticized by developers for its performance. Windows open slowly, loading time is long are old talk about the topic. How can these problems be solved?

The answer is preloading. When displaying the login window, we can open and hide the main window in advance and preload the static resources of the main window. After the user logs in, the main window of IPC message notification is displayed to achieve the effect of opening in seconds. This process can be represented as follows:

In addition to window loading, the Require Node module in Electron is also a fairly expensive operation. Using a large number of native modules directly in the rendering process can seriously slow down page opening times and cause Windows to be interactible, which can be a disastrous experience for desktop applications. NodeIntegration of BrowserWindow has been turned off by default in versions after Electron@5, and as you can see the Electron team does not recommend using native modules directly in the rendering process.

In desktop applications, the wait is unbearable, and even the slightest lack of performance makes the web feel like a shell. To use native modules, we prefer to load modules asynchronously or call them in the main process using asynchronous IPC. In addition, to optimize the user experience, we also need to work on small animations, such as skeleton screens and so on.

The Atom team improved Electron’s loading performance by 30% by using V8 Snapshot capabilities to remove low-performing require calls in production, while also improving application security. Here’s How Atom Uses Chromium Snapshots describe what they did.

Comparison before and after enabling skeleton screen:

Performance tuning is not limited to the above approach. For example, if the asAR function of electron Builder is enabled, the source code will be generated into binary ASAR files during packaging, which can reduce the cost of require operation and slightly reduce the space occupation. The cost is that you can’t use child_process.spawn for files in ASAR; For computation-intensive functions, you can run an extra render process or use require(‘child_process’).spawn to avoid blocking the main process and causing the application to freeze.

volume

Also criticised by developers is the size of Electron’s app. An empty Electron project takes up nearly a hundred megabytes of space when packed. The reason for Electron’s bulk is that, in addition to the Chromium kernel, most of its bulk comes from user-installed node_modules.

If you do not pack the electron application using the electron builder, all the contents in node_modules will be packed, resulting in a large application volume. In this case, there are a number of optimizations we can make:

  1. Run the yarn autoclean command. The node_modules directory contains a large number of README files, documents, and so on, which are not necessary in a production environment. If the project uses YARN for dependency management, run the yarn autoclean command. This command initializes a default configuration file,.yarnclean. Yarn automatically clears dependencies according to. Yarnclean after dependencies are installed.

     The default.yarnclean file looks like this:
     
     # test directories
     __tests__
     test
     tests
     powered-test
     
     # asset directories
     docs
     doc
     website
     assets
     
     # examples
     example
     examples
     
     ...
    Copy the code
  2. Use a dual package.json schema. The node_modules directory also contains devDependencies, which should not be packaged. To solve this problem, electron builder provides a dual package.json architecture. Specifically, electric-Builder recommends that users divide their Electron application dependencies into two parts: development dependencies and production dependencies. Users use package.json in the project root directory to manage development dependencies, and package.json in the project’s application folder to manage production dependencies. The electron builder will only package dependencies in the application folder.

    After this change, the application dependency needs to be installed using the electron Builder install-app-deps command. This action is recommended to be placed in the post-install script within package.json.

    Dependencies in devDependencies are not packaged after electron-builder@8. This means that we can avoid the problem of development dependencies being packaged in this way. If your project is packaged using a tool like WebPack, take care to exclude resources already packaged by Webpack from Dependencies to avoid repeated packaging.

In the future

Ability to the Web,

At present, most of the project’s capabilities are still based on the capabilities provided by Electron. This is equivalent to a serious coupling with Electron, which is not conducive to the reuse of individual capabilities in the project. In the future, we hope to adjust the architecture of the project and carry out plug-in transformation of core capabilities, so as to facilitate the transplantation and reuse of capabilities, and even the future research and development of cloud, which depends on the Web of the core capabilities of the project. Of course, webization will also bring additional performance losses, which will put new requirements on the performance of our project.

Collapse treatment

The stability of the project is also the direction of future efforts. Sometimes we receive feedback from users about application flashbacks, freezes and other phenomena, but we are unable to reproduce them. In many cases, it is difficult to solve the problems of user feedback. In the future, we need to add a mechanism of abnormal monitoring and reporting to the project, collect key information such as operating system information and memory usage, and report or even push alarm messages when Crash occurs. This is beneficial for developers to further understand the user’s use process, convenient problem recurrence.

summary

Electron has a big advantage in terms of efficiency when developing desktop applications. A few lines of JS code can launch a desktop client, greatly reducing the barrier to development. However, Electron also has weaknesses in performance, volume and other aspects. If the early development is not fully considered, it is likely to pay a painful price in the later optimization. In this project, our optimization work is far from enough. We will share more breakthroughs with you in the future.


The resources

[1]Electron: www.electronjs.org/

[2]Electron Fiddle: www.electronjs.org/fiddle

[3] Scaffolding: github.com/search?q=el…

[4]NW.js: nwjs.io/

[5] electron – react – typescript: github.com/Robinfr/ele…

[6] SRC/main/main. Ts: github.com/Robinfr/ele…

[7] SRC/renderer/app. The TSX: github.com/Robinfr/ele…

[8]Devtron: www.electronjs.org/devtron

[9]How to fix Atom bugs: flight-manual.atom. IO /behind Atom…


Welcome to the bump Lab blog: AOtu.io

Or pay attention to the bump Laboratory public account (AOTULabs), push the article from time to time: