User Tools

Site Tools


guida_operativa_per_creare_applicazioni_npm

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
guida_operativa_per_creare_applicazioni_npm [2026/04/02 11:10]
team
guida_operativa_per_creare_applicazioni_npm [2026/04/17 16:34] (current)
lorenzodm
Line 1: Line 1:
 ====== Guida operativa per creare applicazioni npm desktop con Electron, Vite ed electron-builder ====== ====== Guida operativa per creare applicazioni npm desktop con Electron, Vite ed electron-builder ======
  
-Base di partenza: configurazione ​`package.jsonin stile LibrePM+Base di partenza: configurazione ​''​package.json'' ​in stile LibrePM 
  
 ===== 1. Scopo della guida ===== ===== 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:+Questa guida spiega come usare una configurazione ​**npm + Electron + Vite + electron-builder** simile a quella del progetto LibrePM per creare nuove applicazioni desktop che:
  
   * si sviluppano con tooling npm moderno   * si sviluppano con tooling npm moderno
   * usano una UI web locale renderizzata in Electron   * usano una UI web locale renderizzata in Electron
   * generano build desktop multipiattaforma   * generano build desktop multipiattaforma
-  * producono anche pacchetti **.deb** installabili su Debian/​Ubuntu e derivate in modo ordinato +  * producono anche pacchetti **''​.deb''​** installabili su Debian/​Ubuntu e derivate in modo ordinato 
-  * possono includere anche risorse esterne, ad esempio un backend ​`.jar`, binari, template, file statici o altri asset di runtime+  * possono includere anche risorse esterne, ad esempio un backend ​''​.jar''​, binari, template, file statici o altri asset di runtime
  
 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. 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 ===== ===== 2. Cosa fa questa configurazione e perché è una buona base =====
  
-Il `package.jsondi LibrePM implementa una pipeline molto concreta:+Il ''​package.json'' ​di LibrePM implementa una pipeline molto concreta:
  
-  * Vite costruisce il frontend +  ​* **Vite** costruisce il frontend 
-  * Electron avvia l’app desktop +  ​* **Electron** avvia l’app desktop 
-  * electron-builder impacchetta l’app per macOS, Windows e Linux +  ​* **electron-builder** impacchetta l’app per macOS, Windows e Linux 
-  * la build desktop include anche risorse extra esterne al bundle frontend +  * la build desktop include anche **risorse extra** esterne al bundle frontend 
-  * su Linux sono esplicitati i target ​`AppImage``snap`deb(è possibile il `flatpak ma non è molto stabile) +  * su Linux sono esplicitati i target ​**''​AppImage''​****''​snap''​** ​**''​deb''​** ​(è possibile il **''​flatpak''​** ​ ma non è molto stabile) 
-  * per Linux viene personalizzato anche il blocco ​`desktop`, utile per il file `.desktopcosì da permettere l'​inserimento di icone e altri oggetti utili alla build +  * per Linux viene personalizzato anche il blocco ​**''​desktop''​**, utile per il file ''​.desktop'' ​così da permettere l'​inserimento di icone e altri oggetti utili alla build 
-  * in LibrePM la build completa lancia prima il backend Java con `gradlew bootJar`, poi il frontend Vite, poi il packaging Electron +  * in LibrePM la build completa lancia prima il backend Java con ''​gradlew bootJar''​, poi il frontend Vite, poi il packaging Electron 
-  * NOTA BENE: il backend Java può essere sostituito con uno Python/​Go/​altri linguaggi a scelta, purché si espliciti nel pacchetto e si includa poi tutto il necessario+  ​* **NOTA BENE**: il backend Java può essere sostituito con uno Python/​Go/​altri linguaggi a scelta, purché si espliciti nel pacchetto e si includa poi tutto il necessario
  
 In pratica è una soluzione ideale quando vuoi costruire una **desktop app npm-based** ma con capacità più enterprise rispetto a una semplice web app. 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 ===== ===== 3. Anatomia della configurazione =====
Line 36: Line 41:
 ==== 3.1 Metadati di base ==== ==== 3.1 Metadati di base ====
  
-<code+<code json>
-```json+
 { {
   "​name":​ "​nometuaapp-desktop",​   "​name":​ "​nometuaapp-desktop",​
Line 45: Line 49:
   "​main":​ "​electron/​main.cjs"​   "​main":​ "​electron/​main.cjs"​
 } }
-``` 
 </​code>​ </​code>​
  
 ==== Perché conta ==== ==== Perché conta ====
  
-  * `nameinfluenza il nome tecnico del pacchetto +  * ''​name'' ​influenza il nome tecnico del pacchetto 
-  * `versionviene usata anche negli artefatti prodotti +  * ''​version'' ​viene usata anche negli artefatti prodotti 
-  * `descriptionaiuta packaging e identificazione +  * ''​description'' ​aiuta packaging e identificazione 
-  * `type: "​module"​abilita l’uso di ESM nel progetto Node lato tooling +  * ''​type: "​module"​'' ​abilita l’uso di ESM nel progetto Node lato tooling 
-  * `mainindica l’entrypoint Electron principale+  * ''​main'' ​indica l’entrypoint Electron principale
  
 ==== Nota importante ==== ==== Nota importante ====
  
-In questa configurazione il progetto usa ESM a livello package ma il processo principale Electron è in CommonJS con file `.cjs`  +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: È una scelta pratica e sensata quando vuoi:
  
Line 65: Line 67:
   * meno attrito nel bootstrap Electron   * meno attrito nel bootstrap Electron
   * compatibilità elevata con dipendenze e script di runtime   * compatibilità elevata con dipendenze e script di runtime
 +
 +
  
 ===== 4. Gli script che rendono la pipeline riusabile ===== ===== 4. Gli script che rendono la pipeline riusabile =====
  
-**Script presenti**+==== Script presenti ​====
  
-<code+<code json>
-```json+
 "​scripts":​ { "​scripts":​ {
   "​dev":​ "​concurrently -k \"vite --host 127.0.0.1\"​ \"​wait-on http://​127.0.0.1:​5173 && electron .\"",​   "​dev":​ "​concurrently -k \"vite --host 127.0.0.1\"​ \"​wait-on http://​127.0.0.1:​5173 && electron .\"",​
Line 80: Line 83:
   "​preview":​ "vite preview"​   "​preview":​ "vite preview"​
 } }
-``` 
 </​code>​ </​code>​
  
-**Logica operativa**+==== Logica operativa ​====
  
-  * `devavvia frontend Vite ed Electron insieme +  * ''​dev'' ​avvia frontend Vite ed Electron insieme 
-  * `wait-onevita che Electron parta prima che il renderer sia disponibile +  * ''​wait-on'' ​evita che Electron parta prima che il renderer sia disponibile 
-  * `distesegue la pipeline completa ​con+  * ''​build''​ produce solo il bundle frontend 
-   ​- build del backend +  * ''​dist'' ​esegue la pipeline completa: 
-   ​- build del frontend +  - build del backend 
-   ​- packaging desktop+  - build del frontend 
 +  - packaging desktop
  
-**Perché questa impostazione è utile anche per nuovi progetti**+==== Perché questa impostazione è utile anche per nuovi progetti ​====
  
 Per nuove app puoi mantenere lo stesso schema anche se: Per nuove app puoi mantenere lo stesso schema anche se:
Line 101: Line 104:
  
 Ti basta sostituire la parte centrale della pipeline Ti basta sostituire la parte centrale della pipeline
- 
 Ad esempio: Ad esempio:
  
-<code+<code json>
-```json+
 "​dist":​ "vite build && electron-builder"​ "​dist":​ "vite build && electron-builder"​
-``` 
 </​code>​ </​code>​
  
 oppure oppure
  
-<code+<code json>
-```json+
 "​dist":​ "npm run build:​backend && vite build && electron-builder"​ "​dist":​ "npm run build:​backend && vite build && electron-builder"​
-``` 
 </​code>​ </​code>​
 +
 +
  
 ===== 5. Quando usare questa architettura ===== ===== 5. Quando usare questa architettura =====
Line 133: Line 133:
   * una utility CLI   * una utility CLI
   * una libreria npm   * una libreria npm
 +
 +
  
 ===== 6. Struttura progetto consigliata ===== ===== 6. Struttura progetto consigliata =====
Line 138: Line 140:
 Una struttura chiara per replicare questa configurazione è la seguente Una struttura chiara per replicare questa configurazione è la seguente
  
-<code+<code text>
-```text+
 my-app/ my-app/
 ├─ desktop/ ├─ desktop/
Line 162: Line 163:
    ​└─ libs/    ​└─ libs/
       └─ my-backend.jar       └─ my-backend.jar
-``` 
 </​code>​ </​code>​
  
-**Osservazione importante**+==== Osservazione importante ​====
  
-Nel caso di LibrePM, la cartella ​`desktop/vive dentro un progetto più grande e la build desktop pesca il backend da:+Nel caso di LibrePM, la cartella ​''​desktop/'' ​vive dentro un progetto più grande e la build desktop pesca il backend da:
  
-<code+<code json>
-```json+
 "​from":​ "​../​build/​libs"​ "​from":​ "​../​build/​libs"​
-``` 
 </​code>​ </​code>​
  
 Questa è una soluzione ottima per applicazioni ibride in cui il pacchetto desktop deve incorporare un backend compilato altrove. 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 altri componenti di UI  ​+===== 7. Dipendenze principali ​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. Per nuove app non devi copiarle tutte: devi selezionare solo ciò che serve.
  
-**Dev dependencies essenziali per replicare la pipeline**+==== Dev dependencies essenziali per replicare la pipeline ​====
  
-<code+<code bash>
-```bash+
 npm install -D electron electron-builder vite @vitejs/​plugin-react concurrently wait-on npm install -D electron electron-builder vite @vitejs/​plugin-react concurrently wait-on
 npm install react react-dom npm install react react-dom
-``` 
 </​code>​ </​code>​
  
 Aggiungi poi solo i pacchetti necessari per la tua UI. Aggiungi poi solo i pacchetti necessari per la tua UI.
 +
 +
  
 ===== 8. File minimi per partire ===== ===== 8. File minimi per partire =====
  
-==== 8.1 `electron/​main.cjs` ==== 
  
-<code+==== 8.1 ''​electron/​main.cjs''​ ==== 
-```js+ 
 +<code js>
 const { app, BrowserWindow } = require('​electron'​) const { app, BrowserWindow } = require('​electron'​)
 const path = require('​path'​) const path = require('​path'​)
Line 236: Line 235:
   if (process.platform !== '​darwin'​) app.quit()   if (process.platform !== '​darwin'​) app.quit()
 }) })
-``` 
 </​code>​ </​code>​
  
-==== 8.2 `electron/​preload.cjs` ==== 
  
 +==== 8.2 ''​electron/​preload.cjs''​ ====
 +
 +<code js>
 +const { contextBridge } = require('​electron'​)
 +
 +contextBridge.exposeInMainWorld('​desktopAPI',​ {
 +  ping: () => '​pong'​
 +})
 +</​code>​
 +
 +==== 8.3 ''​src/​main.jsx''​ ====
 +
 +<code jsx>
 +import React from '​react'​
 +import ReactDOM from '​react-dom/​client'​
 +import App from '​./​App'​
 +
 +ReactDOM.createRoot(document.getElementById('​root'​)).render(
 +  <​React.StrictMode>​
 +    <App />
 +  </​React.StrictMode>​
 +)
 +</​code>​
 +
 +==== 8.4 ''​src/​App.jsx''​ ====
 +
 +<code jsx>
 +export default function App() {
 +  return (
 +    <main style={{ padding: 24, fontFamily: '​sans-serif'​ }}>
 +      <​h1>​Nuova app desktop npm</​h1>​
 +      <​p>​Base pronta per Electron + Vite + build .deb</​p>​
 +    </​main>​
 +  )
 +}
 +</​code>​
 +se si è ferrati, è possibile usare TypeScript (che io personalmente conosco meno) è un modo più stabile di usare JavaScript (file .jsx) ma vale solo per progetti che diventano troppo grandi. In LibrePM l'uso del framework React, mi ha permesso di usare diversi workaround rispetto JavaScript e quindi sono riuscito comunque ad essere efficiente.
 +
 +
 +
 +===== 9. ''​package.json''​ modello da cui partire =====
 +
 +Questo esempio conserva la filosofia della configurazione analizzata, ma la rende più didattica e riutilizzabile
 +
 +<code json>
 +{
 +  "​name":​ "​my-desktop-app",​
 +  "​version":​ "​0.1.0",​
 +  "​description":​ "My Desktop App",
 +  "​author":​ {
 +    "​name":​ "Nome Cognome",​
 +    "​email":​ "​nome@example.com"​
 +  },
 +  "​type":​ "​module",​
 +  "​main":​ "​electron/​main.cjs",​
 +  "​scripts":​ {
 +    "​dev":​ "​concurrently -k \"vite --host 127.0.0.1\"​ \"​wait-on http://​127.0.0.1:​5173 && electron .\"",​
 +    "​build":​ "vite build",​
 +    "​dist":​ "vite build && electron-builder",​
 +    "​preview":​ "vite preview"​
 +  },
 +  "​dependencies":​ {
 +    "​react":​ "​^18.3.1",​
 +    "​react-dom":​ "​^18.3.1"​
 +  },
 +  "​devDependencies":​ {
 +    "​@vitejs/​plugin-react":​ "​^4.3.1",​
 +    "​concurrently":​ "​^8.2.2",​
 +    "​electron":​ "​^32.3.3",​
 +    "​electron-builder":​ "​^25.0.5",​
 +    "​vite":​ "​^5.4.2",​
 +    "​wait-on":​ "​^7.2.0"​
 +  },
 +  "​build":​ {
 +    "​appId":​ "​com.example.myapp",​
 +    "​productName":​ "​MyApp",​
 +    "​directories":​ {
 +      "​output":​ "​dist-electron"​
 +    },
 +    "​files":​ [
 +      "​dist/​**/​*",​
 +      "​electron/​**/​*"​
 +    ],
 +    "​extraResources":​ [],
 +    "​mac":​ {
 +      "​category":​ "​public.app-category.productivity",​
 +      "​icon":​ "​src/​assets/​icon.icns",​
 +      "​target":​ [
 +        {
 +          "​target":​ "​dmg",​
 +          "​arch":​ ["​x64",​ "​arm64"​]
 +        }
 +      ]
 +    },
 +    "​win":​ {
 +      "​icon":​ "​src/​assets/​icon.ico",​
 +      "​target":​ [
 +        {
 +          "​target":​ "​nsis",​
 +          "​arch":​ ["​x64"​]
 +        }
 +      ]
 +    },
 +    "​nsis":​ {
 +      "​oneClick":​ false,
 +      "​allowToChangeInstallationDirectory":​ true,
 +      "​createDesktopShortcut":​ true,
 +      "​createStartMenuShortcut":​ true,
 +      "​shortcutName":​ "​MyApp",​
 +      "​artifactName":​ "​MyApp-Setup-${version}.${ext}"​
 +    },
 +    "​linux":​ {
 +      "​icon":​ "​src/​assets/​icon.png",​
 +      "​category":​ "​Office",​
 +      "​target":​ [
 +        "​AppImage",​
 +        "​snap",​
 +        "​deb"​
 +      ]
 +    }
 +  }
 +}
 +</​code>​
 +
 +
 +
 +===== 10. Il cuore della build ''​.deb''​ =====
 +
 +Per ottenere un ''​.deb''​ corretto, i blocchi più importanti sono questi
 +
 +<code json>
 +"​directories":​ {
 +  "​output":​ "​dist-electron"​
 +},
 +"​files":​ [
 +  "​dist/​**/​*",​
 +  "​electron/​**/​*"​
 +],
 +"​linux":​ {
 +  "​icon":​ "​src/​assets/​icon.png",​
 +  "​category":​ "​Office",​
 +  "​target":​ [
 +    "​AppImage",​
 +    "​snap",​
 +    "​deb"​
 +  ],
 +  "​desktop":​ {
 +    "​Icon":​ "/​usr/​share/​icons/​hicolor/​1080x1080/​apps/​librepm-desktop.png"​
 +  }
 +}
 +</​code>​
 +
 +==== Cosa fanno davvero ====
 +
 +=== ''​directories.output''​ ===
 +Definisce dove verranno generati gli artefatti finali
 +
 +=== ''​files''​ ===
 +Specifica cosa entra nel pacchetto applicativo
 +Se dimentichi ''​dist/​**/​*'',​ la UI buildata non entra nel pacchetto
 +Se dimentichi ''​electron/​**/​*'',​ il processo principale può mancare
 +
 +=== ''​linux.target''​ ===
 +Se inserisci ''​deb'',​ electron-builder produrrà anche il pacchetto Debian
 +Se non lo specifichi, i target di default su Linux non coincidono necessariamente con ciò che vuoi distribuire
 +
 +=== ''​linux.icon''​ ===
 +Serve per l’icona dell’app nei pacchetti Linux
 +
 +=== ''​linux.desktop''​ ===
 +Permette di personalizzare il file ''​.desktop''​
 +Nel caso analizzato viene forzata una chiave ''​Icon''​ con un path assoluto nel filesystem Linux installato
 +
 +
 +
 +===== 11. Perché questa configurazione funziona bene anche per i ''​.deb''​ =====
 +
 +
 +La configurazione è valida perché segue quattro regole fondamentali
 +
 +
 +==== Regola 1 ====
 +Il frontend viene compilato prima del packaging
 +
 +Senza ''​vite build'',​ Electron non avrebbe i file statici finali da impacchettare.
 +
 +
 +==== Regola 2 ====
 +Il main process Electron è incluso tra i file del pacchetto
 +
 +"​electron/​../​."​ garantisce che il bootstrap desktop venga distribuito.
 +
 +==== Regola 3 ====
 +I target Linux sono dichiarati esplicitamente
 +
 +Avere ''​deb''​ nel blocco ''​linux.target''​ evita ambiguità e rende la pipeline coerente con l’obiettivo di distribuzione Debian.
 +
 +==== Regola 4 ====
 +Le risorse aggiuntive possono essere incluse
 +
 +''​extraResources''​ consente di trasportare nel pacchetto file che non fanno parte del bundle frontend, ad esempio un ''​.jar''​.
 +
 +
 +
 +===== 12. Come includere backend, eseguibili o asset con ''​extraResources''​ =====
 +
 +Il progetto di partenza usa:
 +
 +<code json>
 +"​extraResources":​ [
 +  {
 +    "​from":​ "​../​build/​libs",​
 +    "​to":​ "​backend-libs",​
 +    "​filter":​ ["​*.jar",​ "​!*-plain.jar"​]
 +  }
 +]
 +</​code>​
 +
 +==== Quando usare questo approccio ====
 +
 +Usa ''​extraResources''​ quando devi includere nel pacchetto finale:
 +
 +  * backend Java (o diverso da Java) compilato
 +  * template documentali
 +  * binari nativi
 +  * modelli ML locali
 +  * database seed
 +  * configurazioni di runtime
 +  * licenze o file di supporto
 +
 +==== Vantaggio pratico ====
 +
 +In questo modo non stai “simulando” il backend lato frontend, ma stai distribuendo una vera applicazione desktop composta da più parti.
 +
 +==== Esempio riutilizzabile per una nuova app ====
 +
 +<code json>
 +"​extraResources":​ [
 +  {
 +    "​from":​ "​./​runtime",​
 +    "​to":​ "​runtime",​
 +    "​filter":​ ["​**/​*"​]
 +  }
 +]
 +</​code>​
 +
 +
 +
 +===== 13. Come leggere le risorse extra a runtime =====
 +
 +Quando l’app è impacchettata,​ i file extra non vanno cercati come in sviluppo.
 +Conviene usare ''​process.resourcesPath''​.
 +
 +Esempio lato main process
 +
 +<code js>
 +const path = require('​path'​)
 +const { app } = require('​electron'​)
 +
 +function getBackendJarPath() {
 +  if (app.isPackaged) {
 +    return path.join(process.resourcesPath,​ '​backend-libs',​ '​my-backend.jar'​)
 +  }
 +
 +  return path.join(__dirname,​ '​../​../​build/​libs/​my-backend.jar'​)
 +}
 +</​code>​
 +
 +Questa distinzione è essenziale per non rompere il ''​.deb''​ installato.
 +
 +
 +
 +===== 14. ''​linux.desktop.Icon''​ e perché va trattato con attenzione =====
 +
 +Nel package analizzato compare:
 +
 +<code json>
 +"​desktop":​ {
 +  "​Icon":​ "/​usr/​share/​icons/​hicolor/​1080x1080/​apps/​librepm-desktop.png"​
 +}
 +</​code>​
 +
 +==== Cosa significa ====
 +
 +Si sta dicendo al file ''​.desktop''​ quale icona usare dopo l’installazione del pacchetto.
 +
 +==== Buona pratica operativa ====
 +
 +Quando replichi questo pattern su una nuova app, devi mantenere coerenza tra:
 +
 +  * nome del pacchetto
 +  * nome dell’icona installata
 +  * path indicato nella chiave ''​Icon''​
 +  * asset realmente presenti nel pacchetto finale
 +
 +==== Regola fondamentale ====
 +
 +Non copiare il path dell’icona “così com’è” da un progetto all’altro
 +Devi sempre verificare che il pacchetto generato installi davvero quel file in quel percorso.
 +
 +==== Come verificarlo ====
 +
 +Dopo la build:
 +
 +<code bash>
 +dpkg -c dist-electron/​*.deb | grep -i icon
 +</​code>​
 +
 +Se il path reale non coincide con quello del file ''​.desktop'',​ il pacchetto può installarsi ma mostrare icona mancante nel menu di sistema.
 +
 +
 +
 +===== 15. Comando completo di distribuzione =====
 +
 +Nel caso analizzato la build è:
 +
 +<code json>
 +"​dist":​ "cd .. && ./gradlew bootJar && cd desktop && vite build && electron-builder"​
 +</​code>​
 +
 +==== Interpretazione ====
 +
 +1. esce dalla cartella desktop
 +2. costruisce il backend Spring Boot
 +3. rientra in desktop
 +4. builda il frontend
 +5. genera gli installer
 +
 +==== Variante consigliata per nuovi progetti solo npm ====
 +
 +<code json>
 +"​dist":​ "vite build && electron-builder"​
 +</​code>​
 +
 +==== Variante con backend Node locale ====
 +
 +<code json>
 +"​dist":​ "npm run build:​backend && vite build && electron-builder"​
 +</​code>​
 +
 +
 +
 +===== 16. Vite ed Electron insieme: regola architetturale corretta =====
 +
 +Nel flusso di sviluppo:
 +
 +  * Vite serve la UI da ''​http://​127.0.0.1:​5173''​
 +  * Electron apre quell’URL in dev
 +  * in produzione Electron carica invece ''​dist/​index.html''​
 +
 +Questo pattern è corretto perché separa bene:
 +
 +  * esperienza di sviluppo
 +  * bundle di produzione
 +
 +==== Pattern da replicare sempre ====
 +
 +<code js>
 +if (isDev) {
 +  win.loadURL('​http://​127.0.0.1:​5173'​)
 +} else {
 +  win.loadFile(path.join(__dirname,​ '​../​dist/​index.html'​))
 +}
 +</​code>​
 +
 +
 +
 +===== 17. Creare nuove app partendo da questa struttura =====
 +
 +==== Procedura rapida ====
 +
 +==== Step 1 ====
 +Crea il progetto
 +
 +<code bash>
 +mkdir my-desktop-app
 +cd my-desktop-app
 +npm init -y
 +</​code>​
 +
 +==== Step 2 ====
 +Installa dipendenze
 +
 +<code bash>
 +npm install react react-dom
 +npm install -D electron electron-builder vite @vitejs/​plugin-react concurrently wait-on
 +</​code>​
 +
 +==== Step 3 ====
 +Crea cartelle
 +
 +<code bash>
 +mkdir electron src
 +mkdir -p src/assets
 +</​code>​
 +
 +==== Step 4 ====
 +Aggiungi i file minimi
 +
 +  * ''​electron/​main.cjs''​
 +  * ''​electron/​preload.cjs''​
 +  * ''​src/​main.jsx''​
 +  * ''​src/​App.jsx''​
 +  * ''​index.html''​
 +  * ''​vite.config.js''​
 +
 +==== Step 5 ====
 +Sostituisci ''​package.json''​ con il template operativo
 +
 +==== Step 6 ====
 +Aggiungi icone reali
 +
 +  * ''​src/​assets/​icon.png''​
 +  * ''​src/​assets/​icon.ico''​
 +  * ''​src/​assets/​icon.icns''​
 +
 +==== Step 7 ====
 +Avvia in sviluppo
 +
 +<code bash>
 +npm run dev
 +</​code>​
 +
 +==== Step 8 ====
 +Genera il pacchetto Linux
 +
 +<code bash>
 +npm run dist
 +</​code>​
 +
 +oppure solo target Linux Debian
 +
 +<code bash>
 +npx electron-builder --linux deb
 +</​code>​
 +
 +
 +
 +===== 18. Verifica seria del ''​.deb''​ =====
 +
 +Dopo la generazione del pacchetto, non fermarti alla sola presenza del file.
 +Controlla sempre:
 +
 +==== Metadati ====
 +
 +<code bash>
 +dpkg -I dist-electron/​*.deb
 +</​code>​
 +
 +==== Contenuto del pacchetto ====
 +
 +<code bash>
 +dpkg -c dist-electron/​*.deb
 +</​code>​
 +
 +==== Installazione locale ====
 +
 +<code bash>
 +sudo apt install ./​dist-electron/​*.deb
 +</​code>​
 +
 +==== Avvio da terminale ====
 +
 +<code bash>
 +my-desktop-app
 +</​code>​
 +
 +oppure il nome eseguibile effettivo installato dal pacchetto.
 +
 +==== Controlli manuali fondamentali ====
 +
 +  * l’app si apre
 +  * l’icona compare nel menu
 +  * il file ''​.desktop''​ è corretto
 +  * il frontend è caricato
 +  * le risorse extra sono leggibili
 +  * eventuali processi backend partono davvero
 +  * la disinstallazione non lascia stato inconsistente
 +
 +
 +
 +===== 19. Errori tipici che rompono i ''​.deb''​ =====
 +
 +==== Errore 1 ====
 +Il frontend non entra nel pacchetto
 +
 +Causa comune:
 +  * ''​vite build''​ non eseguito
 +  * ''​files''​ incompleto
 +
 +==== Errore 2 ====
 +L’app si installa ma apre una finestra bianca
 +
 +Cause comuni:
 +  * path di ''​loadFile''​ sbagliato
 +  * ''​dist''​ non incluso
 +  * asset frontend referenziati con path incompatibili
 +
 +==== Errore 3 ====
 +L’icona non compare
 +
 +Cause comuni:
 +  * ''​linux.icon''​ non coerente
 +  * chiave ''​desktop.Icon''​ con path sbagliato
 +  * nome file icona diverso dal nome installato nel pacchetto
 +
 +==== Errore 4 ====
 +Le risorse extra non si trovano dopo l’installazione
 +
 +Causa comune:
 +  * codice che usa path da sviluppo anche in produzione
 +  * mancato uso di ''​process.resourcesPath''​
 +
 +==== Errore 5 ====
 +Il backend viene compilato ma non incluso
 +
 +Causa comune:
 +  * ''​extraResources''​ punta alla cartella sbagliata
 +  * filtro troppo restrittivo
 +  * il backend non è stato buildato prima di ''​electron-builder''​
 +
 +
 +
 +===== 20. Quando aggiungere un blocco ''​deb''​ dedicato =====
 +
 +Per una prima build funzionante può bastare il blocco ''​linux''​ con target ''​deb''​
 +Per una distribuzione più professionale conviene aggiungere anche un blocco ''​deb''​ separato, ad esempio per gestire meglio:
 +
 +  * maintainer
 +  * priority
 +  * package category
 +  * dipendenze consigliate
 +  * script post install o post remove
 +
 +Schema di esempio:
 +
 +<code json>
 +"​deb":​ {
 +  "​maintainer":​ "Nome Cognome <​nome@example.com>",​
 +  "​priority":​ "​optional",​
 +  "​packageCategory":​ "​office"​
 +}
 +</​code>​
 +
 +Questa è una buona estensione quando il progetto smette di essere “solo una build locale” e diventa un prodotto distribuibile.
 +
 +
 +
 +===== 21. Esempio completo più robusto per Linux Debian =====
 +
 +<code json>
 +"​build":​ {
 +  "​appId":​ "​com.example.myapp",​
 +  "​productName":​ "​MyApp",​
 +  "​directories":​ {
 +    "​output":​ "​dist-electron"​
 +  },
 +  "​files":​ [
 +    "​dist/​**/​*",​
 +    "​electron/​**/​*"​
 +  ],
 +  "​extraResources":​ [
 +    {
 +      "​from":​ "​./​runtime",​
 +      "​to":​ "​runtime",​
 +      "​filter":​ ["​**/​*"​]
 +    }
 +  ],
 +  "​linux":​ {
 +    "​icon":​ "​src/​assets/​icon.png",​
 +    "​category":​ "​Office",​
 +    "​target":​ [
 +      "​AppImage",​
 +      "​snap",​
 +      "​deb"​
 +    ]
 +  },
 +  "​deb":​ {
 +    "​maintainer":​ "Nome Cognome <​nome@example.com>",​
 +    "​priority":​ "​optional",​
 +    "​packageCategory":​ "​office"​
 +  }
 +}
 +</​code>​
 +
 +
 +
 +===== 22. Consiglio architetturale per scrivere nuovo codice =====
 +
 +Se vuoi usare questa configurazione come base per **nuove app npm**, ti consiglio di separare sempre il progetto in tre livelli
 +
 +==== Livello 1 ====
 +Renderer UI
 +Tutto ciò che è React, Vite, componenti, pagine, store e logica di presentazione
 +
 +==== Livello 2 ====
 +Bridge
 +API minime esposte da ''​preload.cjs''​ al frontend
 +
 +==== Livello 3 ====
 +Main process
 +Gestione finestre, file system, processi esterni, avvio backend, integrazioni desktop, notifiche, dialog, shell
 +
 +==== Regola d’oro ====
 +
 +Non mettere logica desktop o privilegiata direttamente nel renderer
 +Tieni il renderer il più possibile come una web app locale e delega al bridge solo ciò che serve davvero.
 +
 +
 +
 +===== 23. Pattern consigliato per nuove app con backend embedded =====
 +
 +Se la tua nuova applicazione deve includere un backend locale, la pipeline consigliata è questa
 +
 +1. build backend
 +2. copia backend tra le ''​extraResources''​
 +3. avvio backend dal main process Electron
 +4. il renderer comunica con il backend tramite HTTP locale o IPC strutturato
 +
 +Questo pattern è particolarmente forte per:
 +
 +  * gestionali locali
 +  * software offline-first
 +  * prodotti enterprise installabili
 +  * app con database locale
 +  * sistemi documentali o PM tool
 +
 +
 +
 +===== 24. Esempio di avvio backend dal main process =====
 +
 +<code js>
 +const { spawn } = require('​child_process'​)
 +const path = require('​path'​)
 +const { app } = require('​electron'​)
 +
 +function getBackendPath() {
 +  if (app.isPackaged) {
 +    return path.join(process.resourcesPath,​ '​backend-libs',​ '​my-backend.jar'​)
 +  }
 +
 +  return path.join(__dirname,​ '​../​../​build/​libs/​my-backend.jar'​)
 +}
 +
 +function startBackend() {
 +  const backendPath = getBackendPath()
 +
 +  const child = spawn('​java',​ ['​-jar',​ backendPath],​ {
 +    detached: false,
 +    stdio: '​ignore'​
 +  })
 +
 +  return child
 +}
 +</​code>​
 +
 +==== Nota ====
 +
 +Questo pattern va adattato con logging, healthcheck,​ shutdown controllato e gestione errori
 +Però come base operativa è già utile e coerente con la configurazione studiata.
 +
 +
 +
 +===== 25. Checklist finale prima di considerare “buona” una base template =====
 +
 +==== Metadati ====
 +  * ''​name''​ corretto
 +  * ''​productName''​ corretto
 +  * ''​appId''​ univoco
 +  * ''​version''​ aggiornata
 +  * ''​author''​ compilato
 +
 +==== File ====
 +  * ''​dist/​**/​*''​ incluso
 +  * ''​electron/​**/​*''​ incluso
 +  * icone presenti
 +  * entrypoint Electron corretto
 +
 +==== Linux Debian ====
 +  * ''​linux.target''​ contiene ''​deb''​
 +  * categoria Linux coerente
 +  * icona Linux coerente
 +  * eventuale blocco ''​deb''​ presente
 +  * eventuale chiave ''​desktop.Icon''​ verificata davvero
 +
 +==== Runtime ====
 +  * ''​loadURL''​ in sviluppo
 +  * ''​loadFile''​ in produzione
 +  * ''​process.resourcesPath''​ usato per risorse extra
 +  * eventuale backend incluso davvero
 +
 +==== Validazione ====
 +  * ''​npm run dev''​ funziona
 +  * ''​npm run dist''​ funziona
 +  * ''​dpkg -I''​ ok
 +  * ''​dpkg -c''​ ok
 +  * installazione locale ok
 +  * avvio post install ok
 +
 +
 +
 +===== 26. Conclusione operativa =====
 +
 +La configurazione analizzata è una **base molto valida** per creare nuove applicazioni desktop npm-based perché unisce:
 +
 +  * semplicità di sviluppo con Vite
 +  * packaging serio con Electron
 +  * distribuzione multipiattaforma con electron-builder
 +  * supporto concreto ai pacchetti ''​.deb''​
 +  * possibilità di includere backend o asset extra nel pacchetto finale
 +
 +Il vero valore di questa impostazione non è solo generare un installer, ma costruire una **struttura standardizzabile** per una famiglia di applicazioni desktop professionali.
 +
 +Se vuoi riutilizzarla bene, non devi limitarti a copiare il ''​package.json''​
 +Devi invece replicare consapevolmente questi principi:
 +
 +  * build separata tra renderer e runtime desktop
 +  * packaging esplicito
 +  * risorse extra gestite correttamente
 +  * path di produzione verificati
 +  * controllo reale del contenuto del ''​.deb''​
 +
 +
 +
 +===== 27. Mini template finale “production-ready starter” =====
 +
 +<code json>
 +{
 +  "​name":​ "​starter-desktop-app",​
 +  "​version":​ "​0.1.0",​
 +  "​description":​ "​Starter desktop app",
 +  "​author":​ {
 +    "​name":​ "Your Name",
 +    "​email":​ "​you@example.com"​
 +  },
 +  "​type":​ "​module",​
 +  "​main":​ "​electron/​main.cjs",​
 +  "​scripts":​ {
 +    "​dev":​ "​concurrently -k \"vite --host 127.0.0.1\"​ \"​wait-on http://​127.0.0.1:​5173 && electron .\"",​
 +    "​build":​ "vite build",​
 +    "​dist":​ "vite build && electron-builder",​
 +    "​dist:​deb":​ "vite build && electron-builder --linux deb"
 +  },
 +  "​dependencies":​ {
 +    "​react":​ "​^18.3.1",​
 +    "​react-dom":​ "​^18.3.1"​
 +  },
 +  "​devDependencies":​ {
 +    "​@vitejs/​plugin-react":​ "​^4.3.1",​
 +    "​concurrently":​ "​^8.2.2",​
 +    "​electron":​ "​^32.3.3",​
 +    "​electron-builder":​ "​^25.0.5",​
 +    "​vite":​ "​^5.4.2",​
 +    "​wait-on":​ "​^7.2.0"​
 +  },
 +  "​build":​ {
 +    "​appId":​ "​com.example.starterdesktopapp",​
 +    "​productName":​ "​StarterDesktopApp",​
 +    "​directories":​ {
 +      "​output":​ "​dist-electron"​
 +    },
 +    "​files":​ [
 +      "​dist/​**/​*",​
 +      "​electron/​**/​*"​
 +    ],
 +    "​linux":​ {
 +      "​icon":​ "​src/​assets/​icon.png",​
 +      "​category":​ "​Office",​
 +      "​target":​ [
 +        "​deb"​
 +      ]
 +    },
 +    "​deb":​ {
 +      "​maintainer":​ "Your Name <​you@example.com>",​
 +      "​priority":​ "​optional",​
 +      "​packageCategory":​ "​office"​
 +    }
 +  }
 +}
 +</​code>​
 +
 +
 +
 +===== 28. Riepilogo in una frase =====
 +
 +Usa questa configurazione come **template per applicazioni desktop npm con Electron**, non come semplice file da copiare: è una pipeline di prodotto, non solo una dipendenza di build.
 +
 +
 +
 +===== 29. Copyright & Release =====
 +Questo documento viene rilasciato con copyright © 2026 di BoostMedia APS ETS. Guida rilasciata con licenza GPL3
 +
 +Per eventuali modifiche aggiungersi qui sotto con data:
  
 +  * Autore originale: Lorenzo DM
 +  * Release: 1.0.0
 +  * Rilasciata il: 31/03/2026
  
guida_operativa_per_creare_applicazioni_npm.1775121054.txt.gz · Last modified: 2026/04/02 11:10 by team