electron/docs/tutorial/application-architecture.md

147 lines
5.3 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Electron Application Architecture
Before we can dive into Electron's APIs, we need to discuss the two process
types available in Electron. They are fundamentally different and important to
understand.
## Main and Renderer Processes
In Electron, the process that runs `package.json`'s `main` script is called
__the main process__. The script that runs in the main process can display a
GUI by creating web pages. An Electron app always has one main process, but
never more.
Since Electron uses Chromium for displaying web pages, Chromium's
multi-process architecture is also used. Each web page in Electron runs in
its own process, which is called __the renderer process__.
In normal browsers, web pages usually run in a sandboxed environment and are not
allowed access to native resources. Electron users, however, have the power to
use Node.js APIs in web pages allowing lower level operating system
interactions.
### Differences Between Main Process and Renderer Process
The main process creates web pages by creating `BrowserWindow` instances. Each
`BrowserWindow` instance runs the web page in its own renderer process. When a
`BrowserWindow` instance is destroyed, the corresponding renderer process
is also terminated.
The main process manages all web pages and their corresponding renderer
processes. Each renderer process is isolated and only cares about the web page
running in it.
In web pages, calling native GUI related APIs is not allowed because managing
native GUI resources in web pages is very dangerous and it is easy to leak
resources. If you want to perform GUI operations in a web page, the renderer
process of the web page must communicate with the main process to request that
the main process perform those operations.
> #### Aside: Communication Between Processes
> In Electron, communicating between the main process and renderer processes,
> is done through the [`ipcRenderer`](../api/ipc-renderer.md) and
> [`ipcMain`](../api/ipc-main.md) modules. There is also an FAQ entry on [how
> to share data between web pages][share-data].
## Using Electron APIs
Electron offers a number of APIs that support the development of a desktop
application in both the main process and the renderer process. In both
processes, you'd access Electron's APIs by requiring its included module:
```javascript
const electron = require('electron')
```
All Electron APIs are assigned a process type. Many of them can only be
used from the main process, some of them only from a renderer process,
some from both. The documentation for each individual API will
state which process it can be used from.
A window in Electron is for instance created using the `BrowserWindow`
class. It is only available in the main process.
```javascript
// This will work in the main process, but be `undefined` in a
// renderer process:
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
```
Since communication between the processes is possible, a renderer process
can call upon the main process to perform tasks through IPC.
```javascript
// In the main process:
const { ipcMain } = require('electron')
ipcMain.handle('perform-action', (event, ...args) => {
// ... do something on behalf of the renderer ...
})
// In the renderer process:
const { ipcRenderer } = require('electron')
ipcRenderer.invoke('perform-action', ...args)
```
Note that code in the renderer may not be trustworthy, so it's important
to carefully validate in the main process requests that come from renderers,
especially if they host third-party content.
## Using Node.js APIs
Electron exposes full access to Node.js both in the main and the renderer
process. This has two important implications:
1) All APIs available in Node.js are available in Electron. Calling the
following code from an Electron app works:
```javascript
const fs = require('fs')
const root = fs.readdirSync('/')
// This will print all files at the root-level of the disk,
// either '/' or 'C:\'.
console.log(root)
```
As you might already be able to guess, this has important security implications
if you ever attempt to load remote content. You can find more information and
guidance on loading remote content in our [security documentation][security].
2) You can use Node.js modules in your application. Pick your favorite npm
module. npm offers currently the world's biggest repository of open-source
code  the ability to use well-maintained and tested code that used to be
reserved for server applications is one of the key features of Electron.
As an example, to use the official AWS SDK in your application, you'd first
install it as a dependency:
```sh
npm install --save aws-sdk
```
Then, in your Electron app, require and use the module as if you were
building a Node.js application:
```javascript
// A ready-to-use S3 Client
const S3 = require('aws-sdk/clients/s3')
```
There is one important caveat: Native Node.js modules (that is, modules that
require compilation of native code before they can be used) will need to be
compiled to be used with Electron.
The vast majority of Node.js modules are _not_ native. Only 400 out of the
~650,000 modules are native. However, if you do need native modules, please
consult [this guide on how to recompile them for Electron][native-node].
[node-docs]: https://nodejs.org/en/docs/
[security]: ./security.md
[native-node]: ./using-native-node-modules.md
[share-data]: ../faq.md#how-to-share-data-between-web-pages