Share pubspec.yaml package dependency versions along multiple local flutter and dart packages
We were solving a similar problem.
AFAIK, there's no built-in or recommended way to do this, so we were inventing some hacks.
In our case, we have core
package that has some shared functionality and common dependencies, if you don't have it, you can still create an artificial one, let's say, shared_dependencies
package, and specify all the shared dependencies there.
Now, let's say, package foo
depends on shared_dependencies
package, and there's dependency bar
defined in shared_dependecies
package that foo
needs to use. There are some ways to do that:
-
Import dependency directly. Since
foo
depends transitively onbar
, you can just writeimport package:bar/bar.dart
and it will work. It's not the best way though:- it's bad practice to import transitive dependency (there's even a linter rule for that);
- auto-import won't work;
-
Export package in
shared_dependencies
package. I.e.shared_dependencies.dart
can contain the following lines:export 'package:bar/bar.dart'
That means that in your
foo
package you can just writeimport 'shared_dependencies/shared_dependencies.dart'
and get access tobar
content.Pros:
- auto-imports work.
Contras:
- if you export several packages, there can be name conflicts (you'll have to hide some names in export);
- if
foo
package depends on onebar
package only, it could be weird to import all shared_dependencies.
-
Export in separate libraries of
shared_dependencies
package. You can group some related packages together in different files, e.g.:bar.dart
:export 'package:bar/bar.dart'
bloc.dart
:export 'package:bloc_concurrency/bloc_concurrency.dart'; export 'package:flutter_bloc/flutter_bloc.dart';
In that case, if you need
bar
package infoo
, you writeimport 'package:shared_dependencies/bar.dart'
; if you needbloc
, you writeimport 'package:shared_dependencies/bloc.dart'
. Auto-imports work as well. -
Add direct dependency to
foo
package, but don't specify version constraints:bar:
This basically means that you need any
bar
package, but sincefoo
also depends onshared_dependencies
, its constraints will be taken into account. This may be needed if you're using some executables frombar
package, as there's a limitation in Dart SDK that doesn't allow to run executables in transitive dependencies.
In our project, we ended up using 2
for the most commonly used packages, 3
for other packages, and 4
for packages with executables that we need to run.
tmaihoff
Updated on January 01, 2023Comments
-
tmaihoff over 1 year
My flutter project depends on several local flutter and dart packages to keep things separated and clean. My folder structure is like this:
main-flutter-project │ lib | test │ pubspec.yaml │ └── local-packages │ └── dart-package-1 │ │ pubspec.yaml │ │ │ └── flutter-package-1 │ │ pubspec.yaml │ │ │ └── flutter-package-2 │ pubspec.yaml ...
Each local package is self contained and can be maintained without touching the main project.
This structure means that I have many
pubspec.yaml
files where I have to keep the dependencies updated. When I use e.g. thebloc
libaraybloc: ^7.2.1
in say 5 packages, I have to update the version in eachpubspec
file separately when a new version is released.Is there a possibility to specify those shared package dependency versions in only one place where the other
pubspec.yaml
files refer to?I've seen this e.g. with Maven where you can specify a property
<junit.version>4.12</junit.version>
and access it from somewhere else<version>${junit.version}</version>
. -
tmaihoff over 2 yearsThank you very much for that detailed answer. That definetly helps a lot! Smart approach, providing it via a shared dependencies package. I will reward you the bounty as soon as possible
-
tmaihoff over 2 yearsone question to
3.
: Just putting a comment above one or more export statements groups them together by the comment name? Did I understand that correctly? You say you could import all bloc dependencies by importingshared_dependencies/bloc.dart
but you don't exportbloc.dart
in that example. You only putbloc.dart
as a comment above the bloc-related exports. That seems odd and I feel like I haven't understood3.
it correctly -
Kirill Bubochkin over 2 years@tmaihoff I meant it to be in different files, probably the formatting was confusing. I've updated this point, hopefully, it's more clear now.
-
tmaihoff over 2 yearsah I see, yeah that makes much more sense. Got it now, thanks!
-
vander2675 almost 2 years@KirillBubochkin How to get method
4:
running with build_runner? I have a local package for my dev_dependencies and can import it in thepubspec.yaml
file of the parent like:dev_dependencies: my_dev_dependency_package: path: '../path/to/package'
But this gives me theCannot run executables in transitive dependencies.
Error. I'm not really getting how to apply Method4.
there. -
Kirill Bubochkin almost 2 years@vander2675 did you add the dependency to the main packages as well?
-
vander2675 almost 2 years@KirillBubochkin no only to the dev_dependencies
-
Kirill Bubochkin almost 2 years@vander2675 yeah, with dev_dependencies it won't work, since they apply only to the package that declared them, they are not added to other packages even as transitive dependencies.