Hi, I'm Terence. This article is a broader technical walkthrough of how Electron works.
Understanding Electron's underlying model is important for anyone building Electron applications. Once you understand the full picture, you make better architectural decisions and you know where to start when something goes wrong.
This article looks at Electron from several angles:
Electron is built on top of two main pieces:
They play different roles.
Chromium is the open-source browser project that Google Chrome is built on. Electron uses Chromium as its rendering engine, which means Electron applications can use modern web technologies such as:
Chromium mainly provides:
Node.js is a JavaScript runtime built on V8. Electron uses Node.js to provide system-level APIs, making it possible for desktop apps to access capabilities far beyond the browser sandbox.
Node.js mainly provides:
Electron applications usually contain:
There is also often a preload layer between them.
The main process is the entry point of the Electron application and is usually responsible for:
BrowserWindowipcMainThe renderer process is responsible for the web-based UI of the application. Each BrowserWindow usually corresponds to one independent renderer process.
Its characteristics include:
Preload scripts run in the renderer environment, but they can also access selected Node.js or Electron capabilities.
Their main uses are:
Electron combines process isolation, context bridging, and IPC to let Chromium and Node.js cooperate in a practical and relatively safe way.
Process isolation is one of Electron's core stability and security mechanisms.
The application is split into:
That means even if one renderer crashes, the rest of the application can often remain alive.
The contextBridge API allows selected Node.js-powered functionality to be safely exposed into the renderer process without exposing the full Node environment directly.
Inter-process communication is the collaboration mechanism between the main process and renderer processes.
Electron provides:
ipcMainipcRendererThrough IPC, the renderer can ask the main process to do things like filesystem access, and the main process can send results or events back.
A desktop framework cannot just look good on the surface. It also needs strong low-level support. Electron's low-level support mainly comes from the following areas.
libchromiumcontent libchromiumcontent is a packaged version of Chromium's content layer. It provides a browser-grade rendering engine independently of the full Chromium browser shell.
It is responsible for:
Inside Electron, it provides the browser side of the runtime that the renderer depends on.
Node.js is the JavaScript runtime that gives Electron access to system-level capabilities.
It brings:
In Electron, Node.js is embedded into the main process and, depending on configuration, partially reachable from the renderer side through preload bridges.
V8 is the JavaScript engine developed by Google. Both Chromium and Node.js use it, and Electron benefits from that shared engine.
It provides:
Electron applications also rely on operating-system APIs through:
fs and netThese are what make it possible for Electron apps to:
Putting all of these layers together is what gives Electron its unusual power.
Whether you need to read Electron's source code depends on your depth of interest. In many cases, just understanding the API surface and configuration is enough. But when you hit difficult problems, source code reading can be extremely valuable.
You can browse the Electron source here:
https://github1s.com/electron/electron/tree/main
Electron
├── build/ - build scripts and configuration
├── buildflags/ - optional compile-time features
├── chromium_src/ - Chromium build integration
├── default_app/ - default Electron app when no user app is supplied
├── docs/ - documentation
├── lib/ - JavaScript/TypeScript source
│ ├── browser/ - main-process-related logic
│ ├── common/ - shared logic
│ ├── isolated_renderer/ - isolated renderer logic
│ ├── node/ - Node.js integration
│ ├── renderer/ - renderer logic
│ ├── sandboxed_renderer/ - sandboxed renderer logic
│ ├── utility/ - utility helpers
│ └── worker/ - worker-related logic
├── npm/ - npm-related scripts and config
├── patches/ - patch files
├── script/ - development and build scripts
├── shell/ - core C++ implementation
│ ├── app/ - application core
│ ├── browser/ - browser-process code
│ ├── common/ - shared code
│ ├── renderer/ - renderer-process code
│ ├── services/ - service-related code
│ └── utility/ - utility code
├── spec/ - Electron test specs
├── spec-chromium/ - Chromium-related tests
├── typings/ - TypeScript type definitionsThe structure is carefully designed. It separates:
while also sharing common code where appropriate.
Electron's source tree is large, but even looking at the application entry gives a decent sense of how startup works.
One key entry file is:
\shell\app\electron_main_delegate.cc
This file defines the ElectronMainDelegate class, which plays a central role during Electron startup.
Its responsibilities include:
BasicStartupComplete() handles early setup such as command-line switches and path providers.PreSandboxStartup() prepares things like the user-data directory and logging.CreateContentBrowserClient() and CreateContentRendererClient() create process-specific clients.LoadResourceBundle() loads localized resource bundles.RunProcess() routes startup logic depending on the type of process being launched.ShouldCreateFeatureList() and ShouldInitializeMojo() control those systems.This file effectively coordinates Electron startup and acts as a bridge between Chromium's content layer and Electron-specific runtime behavior.
The design of a framework's API strongly affects how approachable and productive it feels. Electron's API design is one of the reasons it is relatively pleasant to use.
A few design ideas stand out.
Electron's modular design lets developers use only the pieces they need.
Implementation details:
Benefits:
Electron makes heavy use of events, following the style of Node.js EventEmitter.
Implementation details:
Benefits:
Electron leans heavily toward asynchronous APIs.
Implementation details:
async / await are common in higher-level codelibuvBenefits:
Electron exposes a relatively consistent API across operating systems.
Implementation details:
Benefits:
Through these principles, Electron successfully combines web technologies with native desktop capabilities and creates a powerful, flexible platform for desktop application development.
This article was only a broad technical walkthrough, but even from this level it should be clear that Electron is not just "a browser shell that can run desktop apps."
It has:
Understanding those foundations is very helpful in real Electron work, especially when you start dealing with more complex engineering and product scenarios.