Table of Contents

Guida operativa per creare applicazioni npm desktop con Electron, Vite ed electron-builder

Base di partenza: configurazione `package.json` in stile LibrePM

1. Scopo della guida

Questa guida spiega come usare una configurazione npm + Electron + Vite + electron-builder simile a quella del progetto LibrePM per creare nuove applicazioni desktop che:

L’obiettivo non è solo “far partire Electron”, ma usare una struttura replicabile per nuovi progetti con una pipeline di build pulita, comprensibile e pronta per crescere.

2. Cosa fa questa configurazione e perché è una buona base

Il `package.json` di LibrePM implementa una pipeline molto concreta:

In pratica è una soluzione ideale quando vuoi costruire una desktop app npm-based ma con capacità più enterprise rispetto a una semplice web app.

3. Anatomia della configurazione

Di seguito i punti più importanti della configurazione di partenza e il loro significato operativo

3.1 Metadati di base

```json
{
  "name": "nometuaapp-desktop",
  "version": "0.1.0",
  "description": "NomeTuaApp - Descrizione",
  "type": "module",
  "main": "electron/main.cjs"
}
```

Perché conta

Nota importante

In questa configurazione il progetto usa ESM a livello package ma il processo principale Electron è in CommonJS con file `.cjs`

È una scelta pratica e sensata quando vuoi:

4. Gli script che rendono la pipeline riusabile

Script presenti

```json
"scripts": {
  "dev": "concurrently -k \"vite --host 127.0.0.1\" \"wait-on http://127.0.0.1:5173 && electron .\"",
  "dev:renderer": "vite",
  "dev:electron": "wait-on http://localhost:5173 && electron .",
  "build": "vite build",
  "dist": "cd .. && ./gradlew bootJar && cd desktop && vite build && electron-builder",
  "preview": "vite preview"
}
```

Logica operativa

  1. build del backend
  2. build del frontend
  3. packaging desktop

Perché questa impostazione è utile anche per nuovi progetti

Per nuove app puoi mantenere lo stesso schema anche se:

Ti basta sostituire la parte centrale della pipeline

Ad esempio:

```json
"dist": "vite build && electron-builder"
```

oppure

```json
"dist": "npm run build:backend && vite build && electron-builder"
```

5. Quando usare questa architettura

Usa questa struttura quando vuoi realizzare:

Non è invece la scelta più leggera se vuoi solo:

6. Struttura progetto consigliata

Una struttura chiara per replicare questa configurazione è la seguente

```text
my-app/
├─ desktop/
│  ├─ electron/
│  │  ├─ main.cjs
│  │  └─ preload.cjs
│  ├─ src/
│  │  ├─ assets/
│  │  │  ├─ icon.png
│  │  │  ├─ icon.ico
│  │  │  └─ icon.icns
│  │  ├─ App.jsx
│  │  └─ main.jsx
│  ├─ dist/
│  ├─ dist-electron/
│  ├─ index.html
│  ├─ package.json
│  └─ vite.config.js
├─ backend/
│  └─ ... eventuale backend
└─ build/
   └─ libs/
      └─ my-backend.jar
```

Osservazione importante

Nel caso di LibrePM, la cartella `desktop/` vive dentro un progetto più grande e la build desktop pesca il backend da:

```json
"from": "../build/libs"
```

Questa è una soluzione ottima per applicazioni ibride in cui il pacchetto desktop deve incorporare un backend compilato altrove.

7. Dipendenze principali e loro ruolo

Dipendenze runtime

Nel progetto di partenza sono presenti React, i18n, Bootstrap, charting, drag and drop, datepicker, gantt e altri componenti di UI

Per nuove app non devi copiarle tutte: devi selezionare solo ciò che serve.

Dev dependencies essenziali per replicare la pipeline

```bash
npm install -D electron electron-builder vite @vitejs/plugin-react concurrently wait-on
npm install react react-dom
```

Aggiungi poi solo i pacchetti necessari per la tua UI.

8. File minimi per partire

8.1 `electron/main.cjs`

```js
const { app, BrowserWindow } = require('electron')
const path = require('path')

const isDev = !app.isPackaged

function createWindow() {
  const win = new BrowserWindow({
    width: 1400,
    height: 900,
    webPreferences: {
      preload: path.join(__dirname, 'preload.cjs'),
      contextIsolation: true,
      nodeIntegration: false
    }
  })

  if (isDev) {
    win.loadURL('http://127.0.0.1:5173')
  } else {
    win.loadFile(path.join(__dirname, '../dist/index.html'))
  }
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
```

8.2 `electron/preload.cjs`