The original published on https://lleohao.github.io/2017/09/02/ how to set up environment/Electron development

This project structure was summed up when I wrote the Seven Ox file upload App based on Electron and Angular

This paper mainly introduces how to build an efficient Electron development environment from scratch. The main contents are as follows:

  1. Organize your code with proper directory division

  2. Use NPM Script to simplify development

  3. How do I use hot updates during renderer development

  4. How to use automatic restart during main process development

  5. How do I use Typescript for main process development

  6. How to package and distribute software

Example project address github.com/lleohao/el….

Hao.jser.com/ found this website smelly shameless reprint articles

Directory structure division

Initialize a directory

Start by creating a new project folder the usual way (my sample folder here is called super-electron -base), and then initialize the directory with NPM init.

At present, our development catalog is as follows:

├── Download.txt ├─ Download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txt ├─ download.txtCopy the code

Directory partition

Electron is mainly developed into two parts. The Main Process is responsible for opening the page and calling the resources at the bottom of the system, and the Renderer Process is a common web page window.

The development of the two processes is different. The main process is more like traditional Node development, while the renderer process is normal front-end development. At the same time, they share parts (such as auxiliary functions, data models, etc.), so they can be divided in the following way

Electorn - base ├ ─ ─... ├─ └─ SRC -Code Source ├─ Main-Main Code ├─ renderer-shared-codeCopy the code

Electron quick start

Next, run NPM install electron -d to install electron and add the main field to package.json, which represents the entry file for the entire project. Here we set it to SRC /main/main.js.

Add two files by the way

# src/main.js const { app, BrowserWindow } = require('electron') const path = require('path') const url = require('url') let win function createWindow() { win = new BrowserWindow({ width: 800, height: 600 }) win.loadURL(url.format({ pathname: path.join(__dirname, '.. /renderer/index.html'), protocol: 'file:', slashes: true })) // Open the DevTools. win.webContents.openDevTools() // Emitted when the window is closed. win.on('closed', () => { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. win = null }) } // This method will be called when  Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', createWindow) // Quit when all windows are closed. app.on('window-all-closed', () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform ! == 'darwin') { app.quit() } }) app.on('activate', () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other  windows open. if (win === null) { createWindow() } })Copy the code
<! -- src/renderer/index.html --> <! DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello World! </title> </head> <body> <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

Run electron in the root directory (or./node_modules/.bin/electron.) Start the program

Add this command to package.json to make it easier to start the program later

// package.json "main": "SRC /main/main.js", "scripts": {"start": ". / node_modules/bin/electron. "}, "devDependencies" : {" electron ":" ^ 1.7.5 "}Copy the code

Developing render threads

Rendering thread development is not much different from normal front-end development. For efficiency, we usually choose a front-end development framework, in this case Angular, or other frameworks, as described below.

Import Angular(optional, skipped using other frameworks)

Here I use the Angular-CLI tool to initialize the project

  1. Installing the CLI Tool

    `npm install -g @angular/cli`
    Copy the code
  2. Initialize a directory

    ` ng new electron-base -sd src/renderer -si -sg -st --routing true --styles scss ` 
    Copy the code
  3. Modified. Presents – cli. Json

    "Apps" : [{" root ":" SRC/the renderer ", / / the source file directory outDir ":" the out/the renderer ", / / the output directory "baseHref" : ". / ", / / solve unable to load the file after packaging...}]Copy the code

How to hot update code during development

In front-end development, we can use Webpack to enjoy automatic refresh, hot update and other convenient functions. Then how can we enjoy these functions in the development process of Electron? Here we simply need to modify the main.js file

function isDev() { return process.env['NODE_ENV'] === 'development' } function createWindow() { win = new BrowserWindow({ width: 800, height: 600}) if (isDev()) {// Change the url here to the same url you used when developing the framework win.loadurl ('http://127.0.0.1:4200'); } else { win.loadURL(url.format({ pathname: path.join(__dirname, '.. /renderer/index.html'), protocol: 'file:', slashes: true })) } // Open the DevTools. win.webContents.openDevTools() // Emitted when the window is closed. win.on('closed', () => { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. win = null }) }Copy the code

During the development, we still started a WebPCAk server for development in the previous way, and Electron opened the page through HTTP protocol, so that we could still enjoy functions like code hot update.

Set the environment variable NODE_ENV to distinguish between development and build environments, and add two commands to package.json to facilitate development

"scripts": { "ng": "ng", // angular alias "start": "NODE_EBV=production./node_modules/.bin/electron.", // Add environment variable "dev:renderer": "ng serve" // start render thread development server},Copy the code

Package the render thread code

After development, we need to package the front-end code. It is a good practice to put the package directory of the code in the root directory of the project. Here I set the front-end package directory in the Out/Renderer

Angular projects only need to modify the outDir field in.angular-cli.json; other frameworks can modify it themselves.

Add a package command to package.json

"scripts": { .... "Build :renderer": "ng buidl --prod"Copy the code

Development main thread

The development of the main thread is not much different from the development of the Node program, so I won’t go into details here.

While Node support for ES6 is pretty good, newer standard support is not so good, and you can use tools like Babel to use the latest syntax.

I recommend using Typescript for three main reasons:

  1. Static checking, after all, is the main thread of the code, a little error can be the rhythm of the program directly crashed

  2. Autoprompt, this does not explain

  3. It’s easy to compile, and Typescript configuration is much simpler than Babel configuration files

Using Typescript (skip those not in use)

  1. Install the Typescript

Run NPM install typescript -d

  1. To add the configuration file, add the tsconfig.main.json file in the SRC directory

    { "compilerOptions": { "outDir": ".. // moduleResolution: "node", "emitDecoratorMetadata": ExperimentalDecorators: true, "experimentalDecorators": true, "target": "ES6 ", // Output the code version, es6 is ok since running in Node "module": TypeRoots: [//.d.ts directory "../node_modules/@types"], "lib": [// Optional, add new syntax support for "es2017"]}, "exclude": [// exclude thread directory "renderer"]}Copy the code
  2. Add development and packaging commands to package.json

    "scripts": { ... "Dev :main":" tsc-p./ SRC /tsconfig.main.json -w", // develop "build:main": "tsc-p./ SRC /tsconfig.main.Copy the code

Main thread debugging (using vscode editor)

  1. Add the launch configuration file, create a.vscode folder in the project root directory, and create launch.json in it

    { // Use IntelliSense to learn about possible Node.js debug attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0," "configurations" : [{" type ":" node ", "request" : "launch", "name" : "launch the Program", "CWD" : "${workspaceRoot}", "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron", "program": "${workspaceRoot}/ SRC /main/main.ts", // your main file "sourceMaps": true, "outFiles": [" ${workspaceRoot} / out / / *. * * js "/ / your output file directory]," env ": {" NODE_ENV" : "development"}}}]Copy the code
  2. Use the combination key CTRL + F5 to launch the program

  3. Add breakpoints to the file for debugging

Enable automatic refresh of main thread (optional)

Our rendering thread can automatically refresh the page after code changes, and we can use Nodemon to achieve the same function in the main thread development

  1. Install nodemon

npm install nodemon -D

  1. Modifying a Startup Command

    "scripts": {
        "start": "nodemon --watch src/main --watch src/shared --exec './node_modules/.bin/electron' ./out/main/main.js"
    }Copy the code

Later development only need to run NPM start to achieve automatic refresh of the main thread

Package main thread

We may use other build tools as we develop the main thread. Here we place the main thread package file in the out directory, just like the render thread. The structure of the package directory should be as follows

├─ ├─ ├─ ├─ ├─.... │ ├ ─ ├ ─ sci-1.txt - └─ sci-1.txt - sci-1.txt - sci-1.txtCopy the code

Packaging and publishing

Electron builder can package our program into an executable file, and its configuration information is sent in package.json

The Mac package information is configured here. You can refer to the documentation for details

{" main ", "out/main/main. Js", / / the entry file "scripts" : {... "Pack ":" electronic-builder-m --dir", // Simple pack software for testing "dist": "electronic-builder-m ", // official pack software "build": "NPM run build:renderer && NPM run build:main && NPM run dist", "build": {"appId": Sample ", // modify "MAC ": {"category": "public. App-category. Productivity" // modify}}}Copy the code

Run NPM Build to package the software

The development process

  1. Run NPM run dev:renderer to start rendering thread development

  2. Run NPM run dev:main to start mainline development

  3. Run NPM start to open the Electron program

  4. Run the NPM Build wrapper

Example project address github.com/lleohao/el….