diff --git a/firebase.json b/firebase.json index 3f14cfff74..71191663d9 100644 --- a/firebase.json +++ b/firebase.json @@ -181,7 +181,7 @@ { "source": "/go/ffi", "destination": "/interop/c-interop", "type": 301 }, { "source": "/go/flutter-upper-bound-deprecation", "destination": "https://github.com/flutter/flutter/issues/68143", "type": 301 }, { "source": "/go/macros", "destination": "/language/macros", "type": 301 }, - { "source": "/go/pub-workspaces", "destination": "https://flutter.dev/go/pub-workspace", "type": 301 }, + { "source": "/go/pub-workspaces", "destination": "/tools/pub/workspaces", "type": 301 }, { "source": "/go/non-promo-conflicting-getter", "destination": "/tools/non-promotion-reasons#getter-name", "type": 301 }, { "source": "/go/non-promo-conflicting-non-promotable-field", "destination": "/tools/non-promotion-reasons#field-name", "type": 301 }, { "source": "/go/non-promo-conflicting-noSuchMethod-forwarder", "destination": "/tools/non-promotion-reasons#nosuchmethod", "type": 301 }, @@ -375,6 +375,7 @@ { "source": "/to/doc-comment-references", "destination": "/tools/doc-comments/references", "type": 301 }, { "source": "/to/enforce-lockfile", "destination": "/tools/pub/packages#get-dependencies-for-production", "type": 301 }, { "source": "/to/main-function", "destination": "/language/functions#main", "type": 301 }, + { "source": "/to/pub-workspaces", "destination": "/tools/pub/workspaces", "type": 301 }, { "source": "/to/web-debug-extension", "destination": "https://chromewebstore.google.com/detail/dart-debug-extension/eljbmlghnomdjgdjmbdekegdkbabckhm", "type": 301 }, { "source": "/tools/**/download{,.html,/**}", "destination": "/get-dart", "type": 301 }, diff --git a/src/_data/side-nav.yml b/src/_data/side-nav.yml index b065bf02f5..75272472b0 100644 --- a/src/_data/side-nav.yml +++ b/src/_data/side-nav.yml @@ -163,6 +163,8 @@ permalink: /tools/pub/publishing - title: Writing package pages permalink: /tools/pub/writing-package-pages + - title: Workspaces (monorepo support) + permalink: /tools/pub/workspaces - title: Package reference expanded: false children: diff --git a/src/content/tools/pub/cmd/pub-add.md b/src/content/tools/pub/cmd/pub-add.md index fee7385d4a..a1d32e408f 100644 --- a/src/content/tools/pub/cmd/pub-add.md +++ b/src/content/tools/pub/cmd/pub-add.md @@ -218,5 +218,9 @@ By default, pub precompiles executables in immediate dependencies (`--precompile`). To prevent precompilation, use `--no-precompile`. +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub add` will add +dependencies only to the package in the current directory. {% render 'pub-problems.md' %} diff --git a/src/content/tools/pub/cmd/pub-deps.md b/src/content/tools/pub/cmd/pub-deps.md index a55f2a1e83..c0d3deed01 100644 --- a/src/content/tools/pub/cmd/pub-deps.md +++ b/src/content/tools/pub/cmd/pub-deps.md @@ -79,3 +79,8 @@ Generates output in JSON format. {% render 'pub-problems.md' %} + +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub deps` will list +dependencies for all packages in the workspace, one workspace package at a time. \ No newline at end of file diff --git a/src/content/tools/pub/cmd/pub-downgrade.md b/src/content/tools/pub/cmd/pub-downgrade.md index 7bfcfd1abf..50a581a3cd 100644 --- a/src/content/tools/pub/cmd/pub-downgrade.md +++ b/src/content/tools/pub/cmd/pub-downgrade.md @@ -96,8 +96,6 @@ In offline mode, pub looks only in your local package cache, trying to find a set of versions that work with your package from what's already available. - - ## Options For options that apply to all pub commands, see @@ -122,3 +120,8 @@ resolved versions, and returns a list of the changed constraints. Can be applied to [specific dependencies](#downgrading-specific-dependencies). {% render 'pub-problems.md' %} + +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub downgrade` will +downgrade all dependencies across the workspace. \ No newline at end of file diff --git a/src/content/tools/pub/cmd/pub-lish.md b/src/content/tools/pub/cmd/pub-lish.md index cbdb9457e2..c343963790 100644 --- a/src/content/tools/pub/cmd/pub-lish.md +++ b/src/content/tools/pub/cmd/pub-lish.md @@ -47,3 +47,8 @@ You can either wait a few minutes in between publishing the first and the second to publish the second package immediately, by side-stepping client-side validation. {% render 'pub-problems.md' %} + +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub publish` publishes +the package in the current directory. \ No newline at end of file diff --git a/src/content/tools/pub/cmd/pub-outdated.md b/src/content/tools/pub/cmd/pub-outdated.md index 03616a5d75..a8bf8a5417 100644 --- a/src/content/tools/pub/cmd/pub-outdated.md +++ b/src/content/tools/pub/cmd/pub-outdated.md @@ -193,7 +193,6 @@ When you edit the `pubspec.yaml` file, you generally update the **dependencies** and **dev_dependencies** sections so that each package uses the versions in the **Resolvable** column. - ## Options For options that apply to all pub commands, see @@ -234,6 +233,11 @@ are at the latest version (`--no-up-to-date`). To include up-to-date dependencies, use `--up-to-date`. +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub outdated` lists +all dependencies + {% render 'pub-problems.md' %} [`args`]: {{site.pub-pkg}}/args diff --git a/src/content/tools/pub/cmd/pub-remove.md b/src/content/tools/pub/cmd/pub-remove.md index 7a78fb064a..d4e31c60f5 100644 --- a/src/content/tools/pub/cmd/pub-remove.md +++ b/src/content/tools/pub/cmd/pub-remove.md @@ -39,5 +39,9 @@ By default, pub precompiles executables in immediate dependencies (`--precompile`). To prevent precompilation, use `--no-precompile`. +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub remove` removes +dependencies from the package in the current directory. {% render 'pub-problems.md' %} diff --git a/src/content/tools/pub/cmd/pub-upgrade.md b/src/content/tools/pub/cmd/pub-upgrade.md index 98955f7d39..3b10ffd2cf 100644 --- a/src/content/tools/pub/cmd/pub-upgrade.md +++ b/src/content/tools/pub/cmd/pub-upgrade.md @@ -108,7 +108,6 @@ offline `dart pub upgrade` locks your app to that old version. The next time you are online, you will likely want to run `dart pub upgrade` again to upgrade to a later version. - ## Options The `dart pub upgrade` command supports the @@ -160,4 +159,13 @@ When used with a list of packages to unlock, first the transitive closure of those packages' dependencies (in the current resolution) is computed, and then all those packages are unlocked. +## In a workspace + +In a [Pub workspace](/tools/pub/workspaces) `dart pub upgrade` will +upgrade all dependencies in the shared resolution from across all workspace +packages. + +`dart pub upgrade --major-versions` and `dart pub upgrade --tighten` will update +constraints in all workspace `pubspec.yaml` files. + {% render 'pub-problems.md' %} diff --git a/src/content/tools/pub/glossary.md b/src/content/tools/pub/glossary.md index 8598249efe..5c5f882e00 100644 --- a/src/content/tools/pub/glossary.md +++ b/src/content/tools/pub/glossary.md @@ -307,3 +307,14 @@ since they use the [lockfile](#lockfile) to manage their dependency versions. For more information, see [Pub Versioning Philosophy](/tools/pub/versioning). + +## Workspace + +A collection of packages that are developed together with a +shared resolution of their dependency constraints. +Useful for developing in a monorepo. + +The packages have a shared `pubspec.lock` and `.dart_tool/package_config.json`. + +To learn more about setting up and developing in a workspace, +check out [Pub workspaces](/tools/pub/workspaces). diff --git a/src/content/tools/pub/packages.md b/src/content/tools/pub/packages.md index aa049e45bb..6019984918 100644 --- a/src/content/tools/pub/packages.md +++ b/src/content/tools/pub/packages.md @@ -271,6 +271,7 @@ the pub package manager. * [Creating packages](/tools/pub/create-packages) * [Publishing packages](/tools/pub/publishing) +* [Pub workspaces (monorepo support)](/tools/pub/workspaces) ### Reference diff --git a/src/content/tools/pub/workspaces.md b/src/content/tools/pub/workspaces.md new file mode 100644 index 0000000000..feb5251de5 --- /dev/null +++ b/src/content/tools/pub/workspaces.md @@ -0,0 +1,182 @@ +--- +title: Pub workspaces (monorepo support) +short-title: Workspaces +description: Learn more about pub workspaces, a way to manage package monorepos. +--- + +When working on a project, you might develop multiple Dart packages in the same +version control repository (a _monorepo_). + +For example you might have a directory layout like: + +```plaintext +/ + packages/ + shared/ + pubspec.yaml + pubspec.lock + .dart_tool/package_config.json + client_package/ + pubspec.yaml + pubspec.lock + .dart_tool/package_config.json + server_package/ + pubspec.yaml + pubspec.lock + .dart_tool/package_config.json +``` + +There are some downsides to this setup: + +* You need to run `dart pub get` once for each package. +* You risk ending up with different versions of dependencies for each package, + leading to confusion when context switching between the packages. +* If you open the root folder in your IDE, the dart analyzer will create + separate analysis contexts for each package, increasing memory usage. + +Pub allows you to organize your repository as a _workspace_ using a single +shared resolution for all your packages. +Using workspaces for large repositories reduces the amount of memory +required for analysis, hence improving performance. + +:::note +Using a single shared dependency resolution for all your packages increases +the risks of dependency conflicts, because Dart doesn't allow multiple versions +of the same package. + +If the packages are going to be used together (as is commonly the case), +this risk is a useful feature. It forces you to resolve incompatibilities between +your packages when they arise, rather than when you start using the packages. +::: + +To create a workspace: + +* Add a `pubspec.yaml` at the repository root directory with a `workspace` entry + enumerating the paths to the packages of the repository (the workspace + packages): + + ```yaml + name: _ + publish_to: none + environment: + sdk: ^3.6.0 + workspace: + - packages/helper + - packages/client_package + - packages/server_package + ``` + +* For each of the existing `pubspec.yaml` files, make sure their SDK constraint + is at least `^3.6.0` and add a `resolution` entry: + + ```yaml + environment: + sdk: ^3.6.0 + resolution: workspace + ``` + +* Run `dart pub get` anywhere in the repository. This will: + * Create a single `pubspec.lock` next to the root `pubspec.yaml` that contains + the resolution of all the `dependencies` and `dev_dependencies` of all the + workspace packages. + * Create a single shared `.dart_tool/package_config.json` that maps package + names to file locations. + * Delete any other existing `pubspec.lock` and + `.dart_tool/package_config.json` files next to workspace packages. + +Now the file structure looks like this: + +```plaintext +/ + packages/ + shared/ + pubspec.yaml + client_package/ + pubspec.yaml + server_package/ + pubspec.yaml + pubspec.yaml + pubspec.lock + .dart_tool/package_config.json +``` + +:::version-note +Support for pub workspaces was introduced in Dart 3.6.0. + +To use pub workspaces, all your workspace packages (but not your dependencies) +must have an SDK version constraint of `^3.6.0` or higher. +::: + +## Interdependencies between workspace packages + +If any of the workspace packages depend on each other, they will automatically +resolve to the one in the workspace, regardless of the source. + +Eg. `packages/client_package/pubspec.yaml` might depend on `shared`: + +```yaml +dependencies: + shared: ^2.3.0 +``` + +When resolved inside the workspace, the _local_ version of `shared` will be +used. + +The local version of `shared` would still have to match the constraint +(`^2.3.0`) though. + +But when the package is consumed as a dependency without being part of the +workspace, the original source (here implicitly `hosted`) is used. + +So if `client_package` is published to pub.dev and someone depends on it, they +will get the hosted version of `shared` as a transitive dependency. + +## Dependency overrides in a workspace + +All `dependency_overrides` sections in the workspace packages are respected. +You can also place a `pubspec_overrides.yaml` file next to any of the +workspace `pubspec.yaml` files. + +You can only override a package once in the workspace. To keep overrides organized, +it's preferable to keep `dependency_overrides` in the root `pubspec.yaml`. + +## Running a command in a specific workspace package + +Some pub commands, such as `dart pub add`, and `dart pub publish` operate on a +"current" package. You can either change the directory, or use `-C` to point pub at +a directory: + +```console +$ dart pub -C packages/client_package publish +# Same as +$ cd packages/client_package ; dart pub publish ; cd - +``` + +## Temporarily resolving a package outside its workspace: + +Sometimes you might want to resolve a workspace package on its own, for example +to validate its dependency constraints. + +One way to do this is to create a `pubspec_overides.yaml` file that resets the +`resolution` setting, like so: + +```yaml +# packages/client_package/pubspec_overrides.yaml +resolution: +``` + +Now running `dart pub get` inside `packages/client_package` will create an +independent resolution. + +## Listing all workspace packages + +You can run `dart pub workspace list` to list the packages of a workspace. + +```console +$ dart pub workspace list +Package Path +_ ./ +client_package packages/client_package/ +server_package packages/server_package/ +shared packages/shared/ +```