[{"data":1,"prerenderedAt":28},["ShallowReactive",2],{"articolo-gestire-le-dipendenze-in-flutter-pubspec-version-constraints-e-pub-workspaces":3,"comments-article-gestire-le-dipendenze-in-flutter-pubspec-version-constraints-e-pub-workspaces":27},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"cover_remote_url":10,"cover_credit":11,"video_url":15,"status":16,"published_at":17,"meta_title":18,"meta_description":19,"category":20,"author":24},146,"Gestire le dipendenze in Flutter: pubspec, version constraints e pub workspaces","gestire-le-dipendenze-in-flutter-pubspec-version-constraints-e-pub-workspaces","Capire come pub risolve le versioni evita ore di debug. Guida pratica a constraint semantici, pubspec.lock, dependency_overrides, comandi di aggiornamento e alle pub workspaces introdotte con Dart 3.6.","## Perché le dipendenze meritano attenzione\n\nIn quasi tutti i progetti Flutter il file `pubspec.yaml` cresce fino a 30-40 pacchetti. Finché tutto funziona nessuno lo guarda; poi arriva il giorno in cui `flutter pub get` fallisce con un messaggio del tipo \"version solving failed\", oppure la build della CI usa una versione diversa da quella locale e un widget smette di comportarsi come previsto.\n\nCapire **come pub risolve le versioni** e quali strumenti abbiamo per governarle è una competenza da senior tanto quanto saper scrivere un `CustomPainter`. In questo articolo vediamo constraint semantici, lock file, override, comandi di manutenzione e le **pub workspaces**, disponibili da Dart 3.6 (Flutter 3.27) per i monorepo.\n\n## Anatomia del pubspec.yaml\n\n```yaml\nname: my_app\ndescription: Esempio di gestione dipendenze\npublish_to: none # fondamentale per le app: evita pubblicazioni accidentali\nversion: 1.4.2+37 # versione semantica + build number\n\nenvironment:\n  sdk: ^3.6.0\n  flutter: '>=3.27.0'\n\ndependencies:\n  flutter:\n    sdk: flutter\n  dio: ^5.7.0\n  go_router: ^14.6.0\n  shared_preferences: ^2.3.0\n\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n  build_runner: ^2.4.13\n  flutter_lints: ^5.0.0\n```\n\nTre dettagli che spesso vengono trascurati:\n\n- **`publish_to: none`** su ogni applicazione. Senza questa riga un `dart pub publish` distratto può finire su pub.dev.\n- **`environment`** definisce i vincoli su SDK Dart e Flutter: sono il primo motivo di fallimento della risoluzione quando si aggiorna un pacchetto moderno su un SDK vecchio.\n- **`dev_dependencies`** non finiscono nel bundle finale: code generation, linter e test vanno lì, sempre.\n\n## Come leggere i version constraint\n\nDart usa il **semantic versioning** (`MAJOR.MINOR.PATCH`) e il caret (`^`) è la forma idiomatica:\n\n| Constraint | Significato |\n|---|---|\n| `^5.7.0` | `>=5.7.0 \u003C6.0.0` |\n| `^0.3.1` | `>=0.3.1 \u003C0.4.0` (sotto 1.0.0 il minor è breaking) |\n| `>=2.0.0 \u003C2.5.0` | intervallo esplicito |\n| `2.3.1` | versione esatta (da evitare se non strettamente necessario) |\n| `any` | qualsiasi versione (da evitare sempre) |\n\nLa regola pratica:\n\n- **App**: constraint con caret. Sono abbastanza stretti da proteggere dalle breaking change e abbastanza larghi da ricevere patch e fix di sicurezza.\n- **Package pubblicati**: constraint il più larghi possibile (ma non `any`), perché ogni vincolo stretto che imponi diventa un vincolo per tutti i tuoi utenti e aumenta la probabilità di conflitti.\n\nFissare una versione esatta in un'app sembra \"più sicuro\", ma in realtà è dannoso: basta un altro pacchetto che dipenda da una versione diversa dello stesso package per bloccare completamente la risoluzione.\n\n## pubspec.lock: cosa è e quando committarlo\n\n`pubspec.yaml` dichiara gli **intervalli**, `pubspec.lock` registra le **versioni esatte** effettivamente risolte, incluse tutte le dipendenze transitive.\n\n- Nelle **applicazioni** il lock file va **committato**: garantisce che sviluppatori, CI e build di release usino esattamente le stesse versioni. È la differenza tra una build riproducibile e un \"sul mio computer funziona\".\n- Nei **package riutilizzabili** il lock file **non** va committato (è nel `.gitignore` del template di `dart create`): il consumatore risolverà le versioni nel proprio contesto.\n\nQuando `pubspec.lock` esiste, `flutter pub get` prova a rispettarlo; solo se i constraint non sono più soddisfacibili pub ricalcola.\n\n## I comandi che servono davvero\n\n```bash\n# Aggiungere dipendenze senza editare a mano il file\nflutter pub add dio\nflutter pub add dev:mocktail\nflutter pub add 'go_router:^14.6.0'\n\n# Scaricare le dipendenze rispettando il lock file\nflutter pub get\n\n# Aggiornare alle versioni più alte compatibili con i constraint attuali\nflutter pub upgrade\n\n# Report di ciò che è obsoleto (e cosa è discontinuato)\nflutter pub outdated\n\n# Aggiornare i constraint stessi verso le major successive\nflutter pub upgrade --major-versions\n\n# Albero delle dipendenze in forma compatta\nflutter pub deps -s compact\n\n# Risolvere alle versioni MINIME consentite dai constraint\nflutter pub downgrade\n```\n\nDue comandi meritano una nota.\n\n`flutter pub outdated` distingue tre colonne: *Current* (quella nel lock), *Upgradable* (la più alta compatibile con i constraint) e *Resolvable\u002FLatest*. Se *Current* e *Upgradable* differiscono ti basta `pub upgrade`; se la differenza è con *Latest* devi alzare il constraint, cioè accettare una major con possibili breaking change.\n\n`flutter pub downgrade` è il trucco per **verificare i lower bound** dichiarati. Se il tuo package dichiara `^1.2.0` ma usa un'API introdotta nella `1.5.0`, con `downgrade` la compilazione fallisce e lo scopri prima dei tuoi utenti. Ottimo step da inserire in CI per i package pubblicati.\n\n## Dipendenze non da pub.dev\n\n```yaml\ndependencies:\n  # pacchetto locale nello stesso repository\n  core_models:\n    path: ..\u002Fpackages\u002Fcore_models\n\n  # repository Git (utile per fork o fix non ancora pubblicati)\n  awesome_widget:\n    git:\n      url: https:\u002F\u002Fgithub.com\u002Forg\u002Fawesome_widget.git\n      ref: v2.1.0 # usa un tag o uno SHA, mai 'main'\n      path: packages\u002Fawesome_widget # se è un monorepo\n\n  # repository pub privato\n  internal_sdk:\n    hosted:\n      name: internal_sdk\n      url: https:\u002F\u002Fpub.azienda.it\n    version: ^1.0.0\n```\n\nRegola d'oro per le dipendenze Git: **ancorare sempre a un tag o a uno SHA**. Puntare a un branch significa che la build di oggi può differire da quella di domani, anche con il lock file (che memorizza comunque lo SHA risolto, ma che verrà aggiornato al primo `pub upgrade`).\n\nAttenzione: un package che dipende da path o git **non può essere pubblicato** su pub.dev.\n\n## dependency_overrides: l'antidolorifico, non la cura\n\nQuando due pacchetti richiedono versioni incompatibili di una dipendenza transitiva, pub si arrende. L'escape hatch è:\n\n```yaml\ndependency_overrides:\n  analyzer: ^6.4.1\n  meta: 1.15.0\n```\n\nCosa succede davvero: pub **ignora tutti gli altri constraint** su quel package e usa la versione indicata. Può funzionare benissimo, oppure far esplodere l'app a runtime con `NoSuchMethodError`, perché stai forzando un'API che qualche libreria non si aspetta.\n\nLinee guida:\n\n1. Usalo solo nel pubspec della **root** (nei package pubblicati viene ignorato dai consumatori e genera un warning in fase di publish).\n2. Aggiungi sempre un commento con la data e il link alla issue upstream.\n3. Trattalo come debito tecnico: inserisci un promemoria per rimuoverlo quando esce la versione fixata.\n\nPrima di ricorrere all'override, prova a capire *chi* impone il vincolo:\n\n```bash\nflutter pub deps -s compact | grep analyzer\n```\n\nSpesso il colpevole è una dev_dependency di code generation che puoi semplicemente aggiornare.\n\n## Pub workspaces: un solo lock file per tutto il monorepo\n\nDa **Dart 3.6 \u002F Flutter 3.27** pub supporta nativamente i monorepo con le *workspaces*. L'idea: più package nello stesso repository condividono **una singola risoluzione delle dipendenze**, quindi un solo `pubspec.lock` e un solo `.dart_tool\u002Fpackage_config.json` nella root.\n\nStruttura tipica:\n\n```\nmy_monorepo\u002F\n  pubspec.yaml          \u003C- la root della workspace\n  apps\u002F\n    mobile\u002Fpubspec.yaml\n  packages\u002F\n    core\u002Fpubspec.yaml\n    design_system\u002Fpubspec.yaml\n```\n\nRoot `pubspec.yaml`:\n\n```yaml\nname: _my_monorepo\npublish_to: none\n\nenvironment:\n  sdk: ^3.6.0\n\nworkspace:\n  - apps\u002Fmobile\n  - packages\u002Fcore\n  - packages\u002Fdesign_system\n```\n\nOgni package membro dichiara l'appartenenza:\n\n```yaml\nname: core\npublish_to: none\n\nenvironment:\n  sdk: ^3.6.0\n\nresolution: workspace\n\ndependencies:\n  meta: ^1.15.0\n```\n\nE i riferimenti incrociati restano espressi come dipendenze normali: pub risolve automaticamente verso il package locale se il nome appartiene alla workspace.\n\n```yaml\n# apps\u002Fmobile\u002Fpubspec.yaml\ndependencies:\n  flutter:\n    sdk: flutter\n  core: ^1.0.0\n  design_system: ^0.2.0\n```\n\nI vantaggi concreti:\n\n- **Un solo `flutter pub get`** dalla root aggiorna tutti i package.\n- **Coerenza garantita**: impossibile che l'app usi `dio 5.7` e un package interno `dio 5.4`.\n- **CI più veloce**: una sola cache delle dipendenze, un solo passo di risoluzione.\n\nLe workspaces non sostituiscono completamente strumenti come Melos (che resta utile per orchestrare script, versioning e changelog su N package), ma eliminano la parte più fragile: il bootstrap e il linking dei pacchetti locali.\n\n## Strategia di manutenzione\n\nUn flusso sostenibile per un team:\n\n1. **Settimanale**: `flutter pub outdated` in CI, con report pubblicato. Serve a non accumulare ritardo.\n2. **Patch e minor**: aggiornamento automatizzato (Dependabot o Renovate supportano pub) con la suite di test come gate.\n3. **Major**: una alla volta, su branch dedicato, leggendo il CHANGELOG e il file di migrazione. Mai cinque major in un'unica PR.\n4. **Prima di ogni release**: `flutter pub get` pulito su CI partendo dal lock file committato, mai `pub upgrade` in pipeline di produzione.\n5. **Audit periodico**: controlla nei risultati di `pub outdated` i pacchetti marcati come *discontinued* e verifica su pub.dev punteggio, data dell'ultima pubblicazione e numero di issue aperte prima di introdurre una nuova dipendenza.\n\n## Checklist finale\n\n- Constraint con `^` nelle app, il più larghi possibile nei package pubblicati.\n- `pubspec.lock` committato nelle app, ignorato nei package.\n- Dipendenze Git ancorate a tag o SHA.\n- `dependency_overrides` solo temporanei, documentati e nella root.\n- `pub downgrade` in CI per i package, a verifica dei lower bound.\n- Monorepo su Dart 3.6+: valuta `resolution: workspace` al posto del linking manuale.\n\nUna gestione disciplinata delle dipendenze non rende l'app più veloce né più bella, ma elimina un'intera categoria di problemi che tipicamente si manifestano nel momento peggiore: il giorno della release.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fae77adca-2249-4e0b-b07a-19a532005108.jpg","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1542373285-a85124c4f3e6?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w5NzA2NTJ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3OTM1OTIxMDl8&ixlib=rb-4.1.0&q=80&w=1080",{"name":12,"author_url":13,"photo_url":14},"Mahesh Ranaweera","https:\u002F\u002Funsplash.com\u002F@mahesh_ranaweera","https:\u002F\u002Funsplash.com\u002Fphotos\u002Fhtml-codes-N6cdAF4mfqU",null,"published","2026-11-02T04:01:50+00:00","Dipendenze in Flutter: pubspec, constraint e workspaces","Guida pratica alla gestione delle dipendenze in Flutter: version constraint, pubspec.lock, dependency_overrides, comandi pub e pub workspaces per i monorepo.",{"id":21,"name":22,"slug":23},3,"Best practice","best-practice",{"id":25,"name":26},1,"Flutter Bot",[],1793627150125]