Skip to content

docs(guides): translate the Electron tech guide to English #829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 6, 2025
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
sidebar_position: 10
---
# Usage with Electron

Electron applications have a special architecture consisting of multiple processes with different responsibilities. Applying FSD in such a context requires adapting the structure to the Electron specifics.

```sh
└── src
├── app # Common app layer
│ ├── main # Main process
│ │ └── index.ts # Main process entry point
│ ├── preload # Preload script and Context Bridge
│ │ └── index.ts # Preload entry point
│ └── renderer # Renderer process
│ └── index.html # Renderer process entry point
├── main
│ ├── features
│ │ └── user
│ │ └── ipc
│ │ ├── get-user.ts
│ │ └── send-user.ts
│ ├── entities
│ └── shared
├── renderer
│ ├── pages
│ │ ├── settings
│ │ │ ├── ipc
│ │ │ │ ├── get-user.ts
│ │ │ │ └── save-user.ts
│ │ │ ├── ui
│ │ │ │ └── user.tsx
│ │ │ └── index.ts
│ │ └── home
│ │ ├── ui
│ │ │ └── home.tsx
│ │ └── index.ts
│ ├── widgets
│ ├── features
│ ├── entities
│ └── shared
└── shared # Common code between main and renderer
└── ipc # IPC description (event names, contracts)
```

## Public API rules
Each process must have its own public API. For example, you can't import modules from `main` to `renderer`.
Only the `src/shared` folder is public for both processes.
It's also necessary for describing contracts for process interaction.

## Additional changes to the standard structure
It's suggested to use a new `ipc` segment, where interaction between processes takes place.
The `pages` and `widgets` layers, based on their names, should not be present in `src/main`. You can use `features`, `entities` and `shared`.
The `app` layer in `src` contains entry points for `main` and `renderer`, as well as the IPC.
It's not desirable for segments in the `app` layer to have intersection points

## Interaction example

```typescript title="src/shared/ipc/channels.ts"
export const CHANNELS = {
GET_USER_DATA: 'GET_USER_DATA',
SAVE_USER: 'SAVE_USER',
} as const;

export type TChannelKeys = keyof typeof CHANNELS;
```

```typescript title="src/shared/ipc/events.ts"
import { CHANNELS } from './channels';

export interface IEvents {
[CHANNELS.GET_USER_DATA]: {
args: void,
response?: { name: string; email: string; };
};
[CHANNELS.SAVE_USER]: {
args: { name: string; };
response: void;
};
}
```

```typescript title="src/shared/ipc/preload.ts"
import { CHANNELS } from './channels';
import type { IEvents } from './events';

type TOptionalArgs<T> = T extends void ? [] : [args: T];

export type TElectronAPI = {
[K in keyof typeof CHANNELS]: (...args: TOptionalArgs<IEvents[typeof CHANNELS[K]]['args']>) => IEvents[typeof CHANNELS[K]]['response'];
};
```

```typescript title="src/app/preload/index.ts"
import { contextBridge, ipcRenderer } from 'electron';
import { CHANNELS, type TElectronAPI } from 'shared/ipc';

const API: TElectronAPI = {
[CHANNELS.GET_USER_DATA]: () => ipcRenderer.sendSync(CHANNELS.GET_USER_DATA),
[CHANNELS.SAVE_USER]: args => ipcRenderer.invoke(CHANNELS.SAVE_USER, args),
} as const;

contextBridge.exposeInMainWorld('electron', API);
```

```typescript title="src/main/features/user/ipc/send-user.ts"
import { ipcMain } from 'electron';
import { CHANNELS } from 'shared/ipc';

export const sendUser = () => {
ipcMain.on(CHANNELS.GET_USER_DATA, ev => {
ev.returnValue = {
name: 'John Doe',
email: 'john.doe@example.com',
};
});
};
```

```typescript title="src/renderer/pages/user-settings/ipc/get-user.ts"
import { CHANNELS } from 'shared/ipc';

export const getUser = () => {
const user = window.electron[CHANNELS.GET_USER_DATA]();

return user ?? { name: 'John Donte', email: 'john.donte@example.com' };
};
```

## See also
- [Process Model Documentation](https://www.electronjs.org/docs/latest/tutorial/process-model)
- [Context Isolation Documentation](https://www.electronjs.org/docs/latest/tutorial/context-isolation)
- [Inter-Process Communication Documentation](https://www.electronjs.org/docs/latest/tutorial/ipc)
- [Example](https://github.com/feature-sliced/examples/tree/master/examples/electron)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Electron-приложения имеют особую архитектуру, с

```sh
└── src
├── app # Общий сегмент app
├── app # Общий слой app
│ ├── main # Main процесс
│ │ └── index.ts # Точка входа main процесса
│ ├── preload # Preload скрипт и Context Bridge
Expand Down