Skip to content

Commit bd2be13

Browse files
committed
docs: update with-electron.mdx, add an example
1 parent 7ff2cd5 commit bd2be13

File tree

3 files changed

+72
-107
lines changed

3 files changed

+72
-107
lines changed

i18n/ru/docusaurus-plugin-content-docs/current/guides/tech/with-electron.mdx

Lines changed: 62 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,55 @@ Electron-приложения имеют особую архитектуру, с
77

88
```sh
99
└── src
10-
├── app
11-
├── main # Main процесс
12-
│ ├── widgets
13-
│ ├── features
14-
│ ├── entities
10+
├── app # Общий сегмент app
11+
│ ├── main # Main процесс
12+
│ │ └── index.ts # Точка входа main процесса
13+
│ ├── preload # Preload скрипт и Context Bridge
14+
│ │ └── index.ts # Точка входа preload
15+
│ └── renderer # Renderer процесс
16+
│ └── index.html # Точка входа renderer процесса
17+
├── main
18+
│ ├── services
19+
│ │ └── user
20+
│ │ └── ipc
21+
│ │ ├── get-user.ts
22+
│ │ └── send-user.ts
1523
│ └── shared
16-
├── renderer # Renderer процесс
17-
│ ├── pages
18-
│ ├── widgets
19-
│ ├── features
20-
│ ├── entities
24+
├── renderer
25+
│ └── pages
26+
│ │ ├── settings
27+
│ │ │ ├── ipc
28+
│ │ │ │ ├── get-user.ts
29+
│ │ │ │ └── save-user.ts
30+
│ │ │ ├── ui
31+
│ │ │ │ └── user.tsx
32+
│ │ │ └── index.ts
33+
│ │ └── home
34+
│ │ ├── ui
35+
│ │ │ └── home.tsx
36+
│ │ └── index.ts
2137
│ └── shared
22-
└── shared # Общий код между main и renderer
23-
└── ipc # Описание IPC (наименование event'ов, контракты)
38+
└── shared # Общий код между main и renderer
39+
└── ipc # Описание IPC (наименование event'ов, контракты)
2440
```
2541

2642
## Правила для публичного API
27-
Каждый процесс должен иметь свой публичный API, нельзя импортировать модули из `main` в `renderer`. Общедоступным между процессами кодом является только папка `src/shared`. Она же служит для описания контрактов по взаимодействию процессов.
43+
Каждый процесс должен иметь свой публичный API, как пример, нельзя импортировать модули из `main` в `renderer`.
44+
Общедоступным между процессами кодом является только папка `src/shared`.
45+
Она же необходима для описания контрактов по взаимодействию процессов.
2846

2947
## Дополнительные изменения в стандартной структуре
30-
Предлагается использовать новый сегмент `ipc`, в котором происходит взаимодействие между процессами
31-
Слой `pages`, исходя из названия, не должен присутствовать в `src/main`. Слой `app` в `src` содержит точки входа для `main` и `renderer`, а также IPC.
48+
Предлагается использовать новый сегмент `ipc`, в котором происходит взаимодействие между процессами.
49+
Слои `pages` и `widgets`, исходя из названия, не должен присутствовать в `src/main`, вместо них предлагается в качестве самого верхнего уровня использовать слой `services`.
50+
Слой `app` в `src` содержит точки входа для `main` и `renderer`, а также IPC.
51+
Сегментам в слое `app` нежелательно иметь точек пересечения
3252

3353
## Пример взаимодействия
3454

3555
```typescript title="src/shared/ipc/channels.ts"
3656
export const CHANNELS = {
3757
GET_USER_DATA: 'GET_USER_DATA',
38-
SAVE_SETTINGS: 'SAVE_SETTINGS',
58+
SAVE_USER: 'SAVE_USER',
3959
} as const;
4060

4161
export type TChannelKeys = keyof typeof CHANNELS;
@@ -46,10 +66,11 @@ import { CHANNELS } from './channels';
4666

4767
export interface IEvents {
4868
[CHANNELS.GET_USER_DATA]: {
49-
response: { name: string; email: string; };
69+
args: void,
70+
response?: { name: string; email: string; };
5071
};
51-
[CHANNELS.SAVE_SETTINGS]: {
52-
args: { theme: string; };
72+
[CHANNELS.SAVE_USER]: {
73+
args: { name: string; };
5374
response: void;
5475
};
5576
}
@@ -59,117 +80,51 @@ export interface IEvents {
5980
import { CHANNELS } from './channels';
6081
import type { IEvents } from './events';
6182

83+
type TOptionalArgs<T> = T extends void ? [] : [args: T];
84+
6285
export type TElectronAPI = {
63-
[K in keyof typeof CHANNELS]: IEvents[typeof CHANNELS[K]]['response'] extends void
64-
? (args: IEvents[typeof CHANNELS[K]]['args']) => void
65-
: (args: IEvents[typeof CHANNELS[K]]['args']) => Promise<IEvents[typeof CHANNELS[K]]['response']>;
86+
[K in keyof typeof CHANNELS]: (...args: TOptionalArgs<IEvents[typeof CHANNELS[K]]['args']>) => IEvents[typeof CHANNELS[K]]['response'];
6687
};
6788
```
6889

69-
```typescript title="src/app/preload/context-bridge.ts"
90+
```typescript title="src/app/preload/index.ts"
7091
import { contextBridge, ipcRenderer } from 'electron';
7192
import { CHANNELS, type TElectronAPI } from 'shared/ipc';
7293

7394
const API: TElectronAPI = {
74-
[CHANNELS.GET_USER_DATA]: () => ipcRenderer.invoke(CHANNELS.GET_USER_DATA),
75-
[CHANNELS.SAVE_SETTINGS]: (args) => ipcRenderer.send(CHANNELS.SAVE_SETTINGS, args),
95+
[CHANNELS.GET_USER_DATA]: () => ipcRenderer.sendSync(CHANNELS.GET_USER_DATA),
96+
[CHANNELS.SAVE_USER]: args => ipcRenderer.invoke(CHANNELS.SAVE_USER, args),
7697
} as const;
7798

7899
contextBridge.exposeInMainWorld('electron', API);
79100
```
80101

81-
```typescript title="src/main/widgets/user-manager/ipc/send-user-data.ts"
102+
```typescript title="src/main/services/user/ipc/send-user.ts"
82103
import { ipcMain } from 'electron';
83104
import { CHANNELS } from 'shared/ipc';
84105

85-
ipcMain.handle(CHANNELS.GET_USER_DATA, () => {
86-
return { name: 'John Doe', email: 'john.doe@example.com' };
87-
});
88-
```
89-
90-
```typescript title="src/renderer/page/user-settings/ipc/get-user-data.ts"
91-
import { CHANNELS } from 'shared/ipc';
92-
93-
const getUserData = async () => {
94-
const userData = await window.electron[CHANNELS.GET_USER_DATA]();
106+
export const sendUser = () => {
107+
ipcMain.on(CHANNELS.GET_USER_DATA, ev => {
108+
ev.returnValue = {
109+
name: 'John Doe',
110+
email: 'john.doe@example.com',
111+
};
112+
});
95113
};
96114
```
97115

98-
## Структура вышеописанного примера с дополнениями
116+
```typescript title="src/renderer/page/user-settings/ipc/get-user.ts"
117+
import { CHANNELS } from 'shared/ipc';
99118

100-
Теперь распишем подробнее структуру нашего проекта для большей наглядности. Предположим, что используется React в качестве UI библиотеки
119+
export const getUser = () => {
120+
const user = window.electron[CHANNELS.GET_USER_DATA]();
101121

102-
```sh
103-
└── src
104-
├── app # Общий сегмент app
105-
│ ├── main # Main процесс
106-
│ │ ├── index.ts # Точка входа main процесса
107-
│ │ └── create-window.ts
108-
│ ├── preload # Preload скрипт и Context Bridge
109-
│ │ ├── index.ts # Точка входа preload
110-
│ │ └── context-bridge.ts
111-
│ └── renderer # Renderer процесс
112-
│ ├── index.html # Точка входа renderer процесса
113-
│ ├── app.tsx
114-
│ └── globals.css
115-
├── main
116-
│ ├── widgets
117-
│ │ ├── user-manager
118-
│ │ │ ├── ipc
119-
│ │ │ │ ├── handle-user-data.ts
120-
│ │ │ │ └── handle-user-settings.ts
121-
│ │ │ └── model
122-
│ │ │ └── save-user.ts
123-
│ │ ├── notifications
124-
│ │ │ ├── model
125-
│ │ │ └── notification-manager.ts
126-
│ │ │ └── ipc
127-
│ │ │ └── send-notification.ts
128-
│ ├── features
129-
│ │ ├── user-events-logger
130-
│ │ │ └── model
131-
│ │ │ └── log.ts
132-
│ ├── entities
133-
│ │ └── users
134-
│ └── shared
135-
├── renderer
136-
│ ├── pages
137-
│ │ ├── settings
138-
│ │ │ ├── ipc
139-
│ │ │ │ ├── get-settings.ts
140-
│ │ │ │ └── save-settings.ts
141-
│ │ │ ├── ui
142-
│ │ │ │ └── settings.tsx
143-
│ │ │ └── index.ts
144-
│ │ ├── dashboard
145-
│ │ │ ├── ui
146-
│ │ │ │ └── dashboard.tsx
147-
│ │ │ └── index.ts
148-
│ ├── widgets
149-
│ │ ├── user-manager
150-
│ │ │ ├── ipc
151-
│ │ │ │ ├── get-users.ts
152-
│ │ │ │ └── save-user.ts
153-
│ │ │ ├── ui
154-
│ │ │ │ └── user-widget.tsx
155-
│ │ │ ├── model
156-
│ │ │ │ └── user-state.ts
157-
│ │ │ └── index.ts
158-
│ └── features
159-
│ ├── notifications
160-
│ │ ├── ipc
161-
│ │ │ └── get-notification.ts
162-
│ │ ├── ui
163-
│ │ │ └── notification.tsx
164-
│ │ ├── model
165-
│ │ │ └── state.ts
166-
│ │ └── index.ts
167-
│ └── shared
168-
└── shared # Общий код между main и renderer
169-
└── ipc # Описание IPC (наименование event'ов, контракты)
122+
return user ?? { name: 'John Dont e', email: 'john.donte@example.com' };
123+
};
170124
```
171125

172126
## См. также
173127
- [Документация по моделям процессов](https://www.electronjs.org/docs/latest/tutorial/process-model)
174128
- [Документация по изоляции контекстов](https://www.electronjs.org/docs/latest/tutorial/context-isolation)
175-
- [Документация по IPC](https://www.electronjs.org/docs/latest/tutorial/ipc)
129+
- [Документация по IPC](https://www.electronjs.org/docs/latest/tutorial/ipc)
130+
- [Пример](https://github.com/georgkrom/electron-fsd.git)

src/pages/examples/_config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,5 +426,15 @@ export const examples: Example[] = [
426426
updatedAt: "2024-08-10",
427427
tech: ["react", "redux-toolkit", "typescript"],
428428
},
429+
{
430+
title: "Electron FSD",
431+
description:
432+
'Electron application template using Feature-Sliced Design',
433+
source: "https://github.com/georgkrom/electron-fsd",
434+
preview: require("./img/electron-fsd.png"),
435+
version: VERSIONS.V2,
436+
updatedAt: "2025-06-09",
437+
tech: ["react", "electron", "typescript"],
438+
},
429439
// Reverse the list (last examples should be at the top)
430440
].reverse();
8.07 KB
Loading

0 commit comments

Comments
 (0)