Electron has been using electron for some time, as the best packing tool for cross-end applications, and has been impressed by its ease of use. Previously, it was simple configuration out of the box. Recently, the project has more requirements and more APIS, mainly including:

  1. How to distinguish between systems that package third-party software and run it in child processes?
  2. How to optimize the pack volume of Electron?

Go to the project directory first for later description

. ├ ─ ─ app / / production package. The json │ ├ ─ ─ package. The json │ └ ─ ─ yarn. The lock ├ ─ ─ the build / / third-party resources │ ├ ─ ─ macResources │ └ ─ ─ winResources ├─ dist // Pack application store ├─ electron Build.yml // Config file ├─ icon.icns // Mac Icon ├─ icon.ico // Win│ ├─ Index.bundle.js │ ├──.js │ ├── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ─ Index.html ├── ├.config.js // Pack main.js webpack configuration ├─ yarn.lockCopy the code

Break down the first task:

  1. Distinguish system Electron has some macro variables that can be used directly in files, please refer toFile MacrosThat’s what I need${os}If these do not satisfy you, you can use themenv.ENV_NAMEDefine your own. Need to usecross-envCross-platform guarantee
cross-env CUSTOMER_ENV=anything electron-builder
Copy the code
  1. How to package third-party software Description Electron detects all files except those in the build folder by default. If the specified file-pattern is met, the files are packed. The requirement is to package different third-party software (such as drivers) according to different systems. The method I adopted is:
  2. Cooperate with${os}To name the folder,macResources/winResourcesYou can easily find the corresponding folder using the macro variable “${OS}Resources”
  3. Put both in the Build folder (so nothing is packaged)
  4. There are several ways to pack it in
    1. definefile
    2. defineextraResources
    3. defineextraFiles(The only difference with the former is that the former is not copied tocontent,see) I ended up with configurationfileBecause thefileWith themainIn the same level of directory, the command line path lookup after me is easier to understand (extraResourcesWill be inResourceThis directory, you need../To the next level)

Note that defining the file field means that the default is invalid and you need to include all of them manually. And include wildcards for folders or folders (trying to include a filename directly is not valid)

Note also that if it is an executable file, it cannot be compressed in asAR mode. Set asar: false. If 2,3 is used, there is no such limitation (after all, it is in the parent folder, there is a real path, and it will not be compressed). After comparison, there is no big difference in application volume without using asar, and there is no security, so it is easy to extract and refer to it. You can also use the asarUnpack field to customize the configuration. May refer to

The next step is to get third-party software to run alongside your application. Use the child-process module spawn. In main.js. Pass in the corresponding path. This is not in the electron domain, it’s the NodeJS API.

let childSpawn;
const checkMacOS = (a)= > os.platform() === 'darwin';
if (checkMacOS()) {
  childSpawn = spawn(path.join(__dirname, 'macResources/xxx'));
} else {
  spawn(path.join(__dirname, './winResources/xxx'));
}
Copy the code

Spawn is used because third-party software needs to be terminated after the software is shut down. Win can be terminated automatically, and the MAC needs to specify a PID

  mainWindow.on('closed'.function() {
    if (checkMacOS()) {
      process.kill(childSpawn.pid);
    }
    mainWindow = null
  })
Copy the code

In fact, the volume of such packaging has been much smaller than I did not differentiate platform packaging,(do not differentiate platform will be packaged into both platforms) in the spirit of a simple or endless attitude, can we optimize again? Node_module takes up tens of megabytes, including useless electron and electron builder. No, we have to get rid of it.

You can’t delete it directly, because main.js has a lot of require. So the first step is to use webPack to pack the dependencies together, making sure that target is set to electron-main

There are two options for how to include main.js once packaged

  1. Before usefilesField,webpackAfter themain.jsWildcards and other methods can be used here without further details
  2. useDouble package. JsonThis is kind of interesting. One is developmentpackage.jsonOne is productionpackage.jsonAnd it looks like the project structure is cleaner, so try a wave of specific actions as
  3. Create a newappThe folder will default as the root of the package, so in the configuration filefilesYes the relative path used needs to be modified accordingly
  4. inappCreate a new one inpackage.json, just need to includename, version, descriptionSuch simple information, and if there are non-JS dependencies, such as calledC++Library, that needs to be right heredependenciesI’m not using it, so ignore it for now.

The following is the configuration of Webpack. Since electron is the Chromium kernel itself, there is no need to do compatibility, so Babel is not introduced

const path = require('path');
module.exports = {
  target: 'electron-main'.entry: path.resolve(__dirname, 'main.js'),
  output: {
    path: path.resolve(__dirname, 'app'),
    filename: '[name].js'
  },
  mode: 'production'.node: {
    // Use an absolute path
    __dirname: false,}};Copy the code

The following is the YML configuration of ELECTRON for reference

directories:
  output: ./dist
appId: com.electron.xxx
asar: false
copyright: xxx
productName: xxx
mac:
  target:
    - dmg
  icon: ./icon.icns
dmg:
  contents:
    - x: 130
      'y': 50
      type: dir
      name: Driver
      path: build/macResources/Driver
    - x: 130
      'y': 210
    - x: 400
      'y': 210
      type: link
      path: /Applications
nsis:
  allowToChangeInstallationDirectory: true
  oneClick: false
  menuCategory: true
  include: build/installer.nsh
  allowElevation: true
  perMachine: true
win:
  target: nsis
files:
    - from: ../build/${os}Resources/
      to: ${os}Resources/
    - from: . /
      to: . /
    - from: ../to-build
      to: web
compression: normal
electronVersion: 6.09.
Copy the code

As a result, the resource size was reduced by half due to loading third-party software on demand, and tens of megabytes were lost due to removing node_modules and using WebPack Uglify. Because my third-party software is relatively large, the overall reduction is more than 400 M. In addition, the configuration of compression: normal. After compression, the volume of the installation package is controlled within 150M, which meets the product requirements.