Pub 工作区(monorepo 支持)
在项目开发中,你可能会在同一个版本控制仓库(即monorepo)中开发多个 Dart 包。
例如,你可能有一个如下的目录结构:
/
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
这种设置存在一些缺点:
- 你需要为每个包分别运行一次
dart pub get
。 - 你可能会为每个包得到不同版本的依赖项,从而在包之间切换上下文时造成混淆。
- 如果你在 IDE 中打开根文件夹,Dart 分析器将为每个包创建单独的分析上下文,这会增加内存使用量。
Pub 允许你将仓库组织为一个工作区,为所有包使用单一的共享解析。为大型仓库使用工作区可以减少分析所需的内存量,从而提高性能。
创建工作区
在仓库根目录下添加一个
pubspec.yaml
文件,其中包含一个workspace
条目,列举仓库中包的路径(即工作区包)yamlname: _ publish_to: none environment: sdk: ^3.6.0 workspace: - packages/helper - packages/client_package - packages/server_package
对于每个现有的
pubspec.yaml
文件,请确保其 SDK 约束至少为^3.6.0
,并添加一个resolution
条目yamlenvironment: sdk: ^3.6.0 resolution: workspace
在仓库中的任意位置运行
dart pub get
。这将执行以下操作:- 在根
pubspec.yaml
旁边创建一个单独的pubspec.lock
文件,其中包含所有工作区包的dependencies
和dev_dependencies
的解析结果。 - 创建一个单独的共享
.dart_tool/package_config.json
文件,将包名称映射到文件位置。 - 删除工作区包旁边所有其他现有的
pubspec.lock
和.dart_tool/package_config.json
文件。
- 在根
现在文件结构如下所示:
/
packages/
shared/
pubspec.yaml
client_package/
pubspec.yaml
server_package/
pubspec.yaml
pubspec.yaml
pubspec.lock
.dart_tool/package_config.json
散落文件
#当你将现有 monorepo 迁移到使用 Pub 工作区时,每个 pubspec 旁边都会有现有的“散落” pubspec.lock
和 .dart_tool/package_config.json
文件。这些文件会遮蔽放置在根目录旁边的 pubspec.lock
和 .dart_tool/package_config.json
文件。
因此,pub get
将删除位于根目录与任何工作区包之间(包括工作区包目录本身)的所有 pubspec.lock
和 .dart_tool/package_config.json
文件。
/
pubspec.yaml # Root
packages/
pubspec.lock # Deleted by `pub get`
.dart_tool/package_config.json # Deleted by `pub get`
foo/
pubspec.yaml # Workspace member
pubspec.lock # Deleted by `pub get`
.dart_tool/package_config.json # Deleted by `pub get`
如果工作区根目录与工作区包之间的任何目录包含一个不属于该工作区的“散落” pubspec.yaml
文件,pub get
将报告错误并解析失败。这是因为解析这样的 pubspec.yaml
文件会创建一个 .dart_tool/package_config.json
文件,从而遮蔽根目录下的文件。
例如:
/
pubspec.yaml # Root `workspace: ['foo/']`
packages/
pubspec.yaml # Not workspace member => error
foo/
pubspec.yaml # Workspace member
工作区包之间的相互依赖
#如果任何工作区包相互依赖,它们将自动解析为工作区中的包,无论其来源如何。
例如,packages/client_package/pubspec.yaml
可能依赖于 shared
dependencies:
shared: ^2.3.0
在工作区内解析时,将使用 shared
的本地版本。
但是,shared
的本地版本仍然必须匹配约束(^2.3.0
)。
但是,当包作为依赖项被使用且不属于工作区时,将使用其原始来源(这里隐含的是 hosted
)。
因此,如果 client_package
发布到 pub.dev 并且有人依赖它,他们将获得 shared
的托管版本作为传递依赖项。
工作区中的依赖项覆盖
#工作区包中的所有 dependency_overrides
部分都将被遵守。你还可以将 pubspec_overrides.yaml
文件放在任何工作区 pubspec.yaml
文件的旁边。
在一个工作区中,你只能覆盖一个包一次。为了保持覆盖的组织性,最好将 dependency_overrides
放在根 pubspec.yaml
中。
在特定工作区包中运行命令
#一些 pub 命令,例如 dart pub add
和 dart pub publish
,会针对“当前”包操作。你可以更改目录,或使用 -C
将 pub 指向某个目录。
dart pub -C packages/client_package publish
# Same as
cd packages/client_package ; dart pub publish ; cd -
临时在工作区外解析包
#有时你可能希望单独解析工作区中的包,例如为了验证其依赖约束。
一种方法是创建一个 pubspec_overrides.yaml
文件来重置 resolution
设置,如下所示:
# packages/client_package/pubspec_overrides.yaml
resolution:
现在在 packages/client_package
内部运行 dart pub get
将创建独立的解析。
列出所有工作区包
#你可以运行 dart pub workspace list
来列出工作区中的包。
dart pub workspace list
Package Path
_ ./
client_package packages/client_package/
server_package packages/server_package/
shared packages/shared/