Files
knock-gui/desktop-angular/HOW_TO.md

298 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.

# Пошаговый гайд: как “поднять” существующий Angular-проект из `ui/` внутри нового Electron-проекта `desktop-angular/` (без копирования собранного кода)
Ниже — практичный сценарий: вы создаёте папку `desktop-angular/` с каркасом Electron, подключаете туда исходники Angular (те, что уже лежат в `ui/`), настраиваете общий запуск в dev-режиме и сборку prod-пакета. Никаких переносов уже собранных файлов, всё работает от исходников Angular.
## Что получится в итоге
- Dev-режим: одновременно запускается `ng serve` из `ui/` и Electron, который открывает `http://localhost:4200`.
- Prod-режим: сначала билдится Angular в `ui/dist/...`, затем Electron упаковывает приложение и грузит `index.html` из собранного Angular.
---
## 1) Создаём новый проект `desktop-angular/` для Electron
- В корне репозитория создайте папку `desktop-angular/`:
```bash
mkdir /home/su/projects/articles/embed-gui-article/desktop-angular
cd /home/su/projects/articles/embed-gui-article/desktop-angular
npm init -y
```
- Устанавливаем зависимости Electron и утилиты для дев-сценария:
```bash
npm i -D electron electron-builder concurrently wait-on cross-env
```
Рекомендуемая структура (минимум):
- `desktop-angular/package.json` — скрипты для dev/prod.
- `desktop-angular/src/main/main.js` — основной процесс Electron.
- `desktop-angular/src/preload/preload.js` — безопасный мост.
- (Без `renderer/` — рендерером будет ваш Angular из `ui/`.)
Создайте папки и файлы:
```bash
mkdir -p src/main src/preload
touch src/main/main.js src/preload/preload.js
```
---
## 2) Подключаемся к уже существующему Angular-проекту в `ui/`
Предполагаем, что Angular уже установлен и запускается из `/home/su/projects/articles/embed-gui-article/ui/` стандартными командами:
- Dev: `npm start` (или `ng serve`)
- Build: `npm run build`
Если нет `npm start`, добавьте его в `ui/package.json`:
```json
{
"scripts": {
"start": "ng serve --port 4200 --disable-host-check",
"build": "ng build"
}
}
```
---
## 3) Код `main.js` для Electron (dev: URL, prod: файл из dist)
Создайте простой `BrowserWindow`, который:
- в dev грузит `http://localhost:4200`
- в prod грузит файл `../ui/dist/project-front/browser/index.html`
Обратите внимание на относительные пути: мы опираемся на реальную структуру вашего репо и текущие выходные пути Angular (`ui/dist/project-front/browser` у вас уже есть).
```javascript
// desktop-angular/src/main/main.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
const isDev = process.env.NODE_ENV !== 'production';
function createWindow() {
const win = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
preload: path.join(__dirname, '../preload/preload.js'),
contextIsolation: true,
nodeIntegration: false,
sandbox: true
}
});
win.on('ready-to-show', () => win.show());
if (isDev) {
win.loadURL('http://localhost:4200');
// win.webContents.openDevTools(); // включите по желанию
} else {
// В PROD грузим из собранного Angular
const indexPath = path.resolve(
__dirname,
'../../../ui/dist/project-front/browser/index.html'
);
win.loadFile(indexPath);
}
}
app.whenReady().then(() => {
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
```
---
## 4) Код `preload.js` (минимальная безопасная заготовка)
```javascript
// desktop-angular/src/preload/preload.js
const { contextBridge } = require('electron');
contextBridge.exposeInMainWorld('env', {
isElectron: true
});
```
В Angular вы сможете проверять наличие `window.env?.isElectron`.
---
## 5) Скрипты в `desktop-angular/package.json`
Добавим удобные команды:
- `dev`: параллельно запускает Angular dev-сервер в `ui/` и Electron (ждём порт 4200).
- `build:ui`: сборка Angular.
- `start`: старт Electron в prod-режиме (если нужно локально проверить загрузку собранного Angular без упаковки).
- `dist`: упаковка Electron (electron-builder).
```json
{
"name": "desktop-angular",
"version": "1.0.0",
"private": true,
"main": "src/main/main.js",
"scripts": {
"dev": "concurrently -k -n UI,ELECTRON -c green,cyan \"cd ../ui && npm start\" \"wait-on http://localhost:4200 && cross-env NODE_ENV=development electron .\"",
"build:ui": "cd ../ui && npm run build",
"start": "cross-env NODE_ENV=production electron .",
"dist": "npm run build:ui && cross-env NODE_ENV=production electron-builder"
},
"devDependencies": {
"concurrently": "^9.0.0",
"cross-env": "^7.0.3",
"electron": "^31.0.0",
"electron-builder": "^24.13.3",
"wait-on": "^7.2.0"
}
}
```
---
## 6) Конфигурация упаковки Electron (electron-builder)
Добавьте секцию `build` в `desktop-angular/package.json`. Мы не копируем Angular внутрь `desktop-angular` — Electron будет брать собранный Angular прямо из `ui/dist/...` при упаковке (через `extraResources`). Это удобно и прозрачно.
```json
{
"build": {
"appId": "com.yourcompany.knocker",
"productName": "Knocker Desktop Angular",
"files": [
"src/main/**/*",
"src/preload/**/*",
"package.json"
],
"extraResources": [
{
"from": "../ui/dist/project-front/browser",
"to": "ui-dist",
"filter": ["**/*"]
}
],
"linux": {
"target": ["AppImage"],
"category": "Utility",
"artifactName": "Knocker-Desktop-Angular-${version}.${ext}"
}
}
}
```
И соответствующее изменение в `main.js` на prod, если хотите грузить из `resources/ui-dist` у упакованного приложения:
- В упакованном `.AppImage` ваши ресурсы оказываются в `process.resourcesPath`.
- Тогда путь до `index.html` будет: `path.join(process.resourcesPath, 'ui-dist', 'index.html')`.
Адаптированный prod-фрагмент:
```javascript
// ... в main.js, в ветке !isDev:
const indexPath = app.isPackaged
? path.join(process.resourcesPath, 'ui-dist', 'index.html')
: path.resolve(__dirname, '../../../ui/dist/project-front/browser/index.html');
win.loadFile(indexPath);
```
Так вы покроете оба случая: локальный prod-запуск и реальный упакованный билд.
---
## 7) CORS, безопасность и доступ к файлам
- В dev Angular грузится по `http://localhost:4200` — обычно проблем нет.
- В prod Angular грузится с `file://` — убедитесь, что никакие запросы не завязаны на абсолютные HTTP-URL без необходимости.
- По умолчанию оставляем `contextIsolation: true`, `nodeIntegration: false`, `sandbox: true`. Для доступа к нативному коду используйте IPC и `preload.js`.
---
## 8) Локальный запуск dev
```bash
cd /home/su/projects/articles/embed-gui-article/desktop-angular
npm run dev
```
- Скрипт поднимет `ng serve` из `ui/` и откроет Electron, который загрузит `http://localhost:4200`.
---
## 9) Локальная проверка prod без упаковки
```bash
# Собираем Angular
cd /home/su/projects/articles/embed-gui-article/ui
npm run build
# Запускаем Electron в prod-режиме
cd /home/su/projects/articles/embed-gui-article/desktop-angular
npm run start
```
---
## 10) Упаковка приложения
```bash
cd /home/su/projects/articles/embed-gui-article/desktop-angular
npm run dist
```
- Angular соберётся.
- Electron-упаковщик положит содержимое `ui/dist/project-front/browser` в `resources/ui-dist`.
- Приложение загрузит `index.html` из `resources/ui-dist`.
---
## 11) Советы по интеграции Angular и Electron
- Детект среды в Angular:
```typescript
// пример: app.component.ts
isElectron = typeof (window as any).env?.isElectron === 'boolean';
```
- Статические пути: В Angular используйте относительные пути к ассетам, чтобы они работали и в `http://localhost:4200`, и в `file://` в prod.
- IPC: если потребуется обмен с main-процессом, расширяйте `preload.js` и опишите чёткий API через `contextBridge`.
---
## 12) Итоговая структура (ключевые узлы)
- `ui/` — как есть, исходники Angular.
- `desktop-angular/`
- `package.json` — скрипты `dev`, `build:ui`, `start`, `dist`, секция `build` (electron-builder).
- `src/main/main.js` — создаёт окно, грузит URL в dev и файл в prod.
- `src/preload/preload.js` — мост в рендерер.
- Ничего из `ui/` внутрь `desktop-angular/` мы не копируем; работаем поверх исходников.
---
## Что делать, если вы хотите переиспользовать текущую папку `desktop/`?
Можно; у вас уже есть `desktop/` с Electron. Тогда:
- Либо перенести логику оттуда в `desktop-angular/` (описано выше).
- Либо в существующем `desktop/` заменить рендерер на Angular из `ui/` по тем же принципам: dev — `loadURL('http://localhost:4200')`, prod — `loadFile(...)` на `ui/dist/...`.