跳到主要內容

包依賴

依賴是 pub 包管理器的核心概念之一。依賴項是您的包正常工作所需的另一個包。依賴項在您的 pubspec 中指定。您只列出直接依賴項:您的包直接使用的軟體。Pub 會為您處理傳遞依賴項

本頁面詳細介紹瞭如何指定依賴項。最後列出了包依賴項的最佳實踐

概覽

#

對於每個依賴項,您需要指定所依賴包的名稱以及允許的該包的版本範圍。您還可以指定。源告訴 pub 如何定位包。

例如,您可以按以下格式指定依賴項

yaml
dependencies:
  transmogrify: ^1.0.0

此 YAML 程式碼建立了對 transmogrify 包的依賴,使用預設包倉庫 (pub.dev),並允許從 1.0.02.0.0(但不包括 2.0.0)的任何版本。要了解此語法,請檢視版本約束

要指定除 pub.dev 之外的源,請使用 sdkhostedgitpath。例如,以下 YAML 程式碼使用 path 來告訴 pub 從本地目錄獲取 transmogrify

yaml
dependencies:
  transmogrify:
    path: /Users/me/transmogrify

下一節將介紹每個依賴項源的格式。

依賴來源

#

Pub 可以使用以下源來定位包

託管包

#

託管包是可以從 pub.dev 網站(或支援相同 API 的其他 HTTP 伺服器)下載的包。以下是宣告對託管包依賴的示例:

yaml
dependencies:
  transmogrify: ^1.4.0

此示例指定您的包依賴於名為 transmogrify 的託管包,並且支援從 1.4.0 到 2.0.0(但不包括 2.0.0 本身)的任何版本。

如果您想使用自己的包倉庫,可以使用 hosted 來指定其 URL。以下 YAML 程式碼使用 hosted 源建立了對 transmogrify 包的依賴:

yaml
environment:
  sdk: '^2.19.0'

dependencies:
  transmogrify:
    hosted: https://some-package-server.com
    version: ^1.4.0

版本約束是可選的,但建議使用。如果未指定版本約束,則預設為 any

Git 包

#

有時您走在技術前沿,需要使用尚未正式釋出的包。也許您的包本身仍在開發中,並且正在同時使用其他正在開發的包。為了簡化此過程,您可以直接依賴儲存在 Git 倉庫中的包。

yaml
dependencies:
  kittens:
    git: https://github.com/munificent/kittens.git

這裡的 git 表示此包是使用 Git 找到的,其後的 URL 是可用於克隆此包的 Git URL。

即使包倉庫是私有的,您也可以配置 git 以使用HTTPS 訪問金鑰SSH 金鑰對訪問倉庫。然後,您可以使用倉庫對應的 URL 依賴該包:

yaml
dependencies:
  kittens:
    # SSH URL:
    git: git@github.com:munificent/kittens.git

dart pub 命令會呼叫 git clone 作為子程序,因此您只需提供一個在執行 git clone <url> 時能夠正常工作的 <url>

如果您想依賴特定的提交、分支或標籤,請在描述中新增一個 ref 鍵:

yaml
dependencies:
  kittens:
    git:
      url: git@github.com:munificent/kittens.git
      ref: some-branch

ref 可以是 Git 允許識別提交的任何內容。

Pub 假設包位於 Git 倉庫的根目錄。要指定倉庫中的不同位置,請指定相對於倉庫根目錄的 path

yaml
dependencies:
  kittens:
    git:
      url: git@github.com:munificent/cats.git
      path: path/to/kittens

該路徑是相對於 Git 倉庫根目錄的。

上傳到 pub.dev 的包不允許使用 Git 依賴。

路徑包

#

有時您會同時處理多個相關包。也許您正在構建一個框架,同時也在開發一個使用該框架的應用程式。在這些情況下,在開發期間,您會希望依賴本地檔案系統上該包的即時版本。這樣,一個包中的更改會立即被依賴它的包檢測到。

為了處理這種情況,pub 支援路徑依賴

yaml
dependencies:
  transmogrify:
    path: /Users/me/transmogrify

這表示 transmogrify 的根目錄是 /Users/me/transmogrify。對於此依賴項,pub 會直接為引用包目錄的 lib 目錄生成一個符號連結。您對依賴包所做的任何更改都會立即生效。您無需每次更改依賴包時都執行 pub。

允許使用相對路徑,並將其視為相對於包含您的 pubspec 檔案的目錄。

路徑依賴對於本地開發很有用,但在與外界共享程式碼時不起作用——並非所有人都能訪問您的檔案系統。因此,如果您的包在 pubspec 中有任何路徑依賴,您就無法將其上傳到 pub.dev 網站

相反,典型的工作流程是

  1. 在本地編輯您的 pubspec 以使用路徑依賴。
  2. 開發主包及其依賴的包。
  3. 一旦它們都能正常工作,就釋出依賴包。
  4. 更改您的 pubspec,使其指向現在託管的依賴包版本。
  5. 如果需要,也釋出您的主包。

SDK

#

SDK 源用於隨包一起釋出的任何 SDK,這些 SDK 本身也可能是依賴項。目前,Flutter 是唯一受支援的 SDK。

語法如下所示

yaml
dependencies:
  flutter_driver:
    sdk: flutter

sdk: 後面的識別符號表示該包來自哪個 SDK。如果它是 flutter,則只要滿足以下條件,該依賴項就可滿足:

  • Pub 在 flutter 可執行檔案的上下文中執行
  • Flutter SDK 包含具有給定名稱的包

如果它是一個未知識別符號,則該依賴項始終被視為未滿足。

版本約束

#

假設您的包 A 依賴於包 B。您如何向其他開發者表明包 B 的哪個版本與包 A 的給定版本相容?

為了讓開發者瞭解版本相容性,請指定版本約束。您希望允許儘可能寬的版本範圍,以提供包使用者靈活性。該範圍應排除不相容或未經測試的版本。

Dart 社群使用語義化版本控制1

從 Dart 2.19 開始,您可以使用傳統語法插入符語法來表達版本約束。兩種語法都指定了相容的版本範圍。

傳統語法提供了一個明確的範圍,如 '>=1.2.3 <2.0.0'。插入符語法提供了一個明確的起始版本 ^1.2.3

yaml
environment:
  # This package must use a 3.x version of the Dart SDK starting with 3.2.
  sdk: ^3.2.0

dependencies:
  transmogrify:
    hosted:
      name: transmogrify
      url: https://some-package-server.com
    # This package must use a 1.x version of transmogrify starting with 1.4.
    version: ^1.4.0

要了解更多關於 pub 的版本系統,請參閱包版本控制頁面

傳統語法

#

使用傳統語法的版本約束可以使用以下任何值

允許使用?備註
任意所有版本用作空版本約束的明確宣告。
1.2.3僅給定版本由於對使用您包的應用程式施加了額外限制,因此限制了您包的採用。
>=1.2.3給定版本或更高版本
>1.2.3晚於給定版本的版本
<=1.2.3給定版本或更早版本
<1.2.3早於給定版本的版本當您知道某個上限版本相容您的包時,請使用此項。此版本可能是引入某些破壞性變更的第一個版本。

您可以指定版本值的任意組合,只要它們的範圍有交集。例如,如果您將版本值設定為 '>=1.2.3 <2.0.0',這將結合這兩個限制,因此依賴項可以是 1.2.32.0.0(不包括 2.0.0 本身)之間的任何版本。

插入符語法

#

插入符語法以緊湊的方式表達版本約束。^version 意味著保證與給定版本向後相容的所有版本範圍。此範圍將包括所有版本,直到下一個引入破壞性變更的版本。由於 Dart 使用語義化版本控制,對於任何 1.0 或更高版本的包,這將是下一個主要版本;對於任何早於 1.0 版本的包,這將是下一個次要版本。

版本值範圍涵蓋至插入符語法傳統語法
>=1.0下一個主要版本^1.3.0'>=1.3.0 <2.0.0'
<1.0下一個次要版本^0.1.2'>=0.1.2 <0.2.0'

以下示例展示了插入符語法

yaml
dependencies:
  # Covers all versions from 1.3.0 to 1.y.z, not including 2.0.0
  path: ^1.3.0
  # Covers all versions from 1.1.0 to 1.y.z, not including 2.0.0
  collection: ^1.1.0
  # Covers all versions from 0.1.2 to 0.1.z, not including 0.2.0
  string_scanner: ^0.1.2

開發依賴

#

Pub 支援兩種型別的依賴:常規依賴和開發依賴。開發依賴與常規依賴的不同之處在於,您所依賴的包的開發依賴會被忽略。例如:

假設 transmogrify 包在其測試中(且僅在其測試中)使用了 test 包。如果有人只是想使用 transmogrify——匯入其庫——那麼它實際上並不需要 test。在這種情況下,它會將 test 指定為開發依賴。它的 pubspec 會類似這樣:

yaml
dev_dependencies:
  test: ^1.25.0

Pub 會獲取您的包所依賴的每個包,以及這些包所傳遞依賴的所有內容。它還會獲取您包的開發依賴,但會忽略任何被依賴包的開發依賴。Pub 只獲取您自己包的開發依賴。因此,當您的包依賴 transmogrify 時,它將獲取 transmogrify 但不獲取 test

決定使用常規依賴還是開發依賴的規則很簡單:如果依賴項是從您的 libbin 目錄中的內容匯入的,則它需要是一個常規依賴。如果它只從 testexample 等目錄匯入,則它可以而且應該是一個開發依賴。

使用開發依賴可以使依賴圖更小。這使得 pub 執行更快,並且更容易找到滿足所有約束的包版本集。

依賴覆蓋

#

您可以使用 dependency_overrides 來暫時覆蓋所有對依賴項的引用。

例如,您可能正在更新已釋出的包 transmogrify 的本地副本。Transmogrify 在您的依賴圖中被其他包使用,但您不想在本地克隆每個包並更改每個 pubspec 以測試您本地的 transmogrify 副本。

在這種情況下,您可以使用 dependency_overrides 來覆蓋依賴項,指定包含包本地副本的目錄。

pubspec 檔案看起來會像下面這樣

yaml
name: my_app
dependencies:
  transmogrify: ^1.2.0
dependency_overrides:
  transmogrify:
    path: ../transmogrify_patch/

當您執行 dart pub getdart pub upgrade 時,pubspec 的 lockfile 會更新以反映您依賴項的新路徑,並且無論何處使用 transmogrify,pub 都會使用本地版本。

您還可以使用 dependency_overrides 來指定包的特定版本:

yaml
name: my_app
dependencies:
  transmogrify: ^1.2.0
dependency_overrides:
  transmogrify: '3.2.1'

在包解析過程中,只考慮 包自身 pubspec 中的依賴覆蓋。任何被依賴包內部的依賴覆蓋都會被忽略。

因此,如果您將包釋出到 pub.dev,請記住,您的包的依賴覆蓋會被您包的所有使用者忽略。

如果您正在使用 pub 工作區,則每個工作區包都可以有 dependency_overrides,但在工作區中,單個包只能被覆蓋一次。

pubspec_overrides.yaml

#

如果您想更改 pubspec.yaml 檔案解析的某些方面,但又不想更改實際檔案,可以在 pubspec.yaml 旁邊放置一個名為 pubspec_overrides.yaml 的檔案。

該檔案中的屬性將覆蓋 pubspec.yaml 中的屬性。

可以覆蓋的屬性有

  • dependency_overrides
  • workspace
  • resolution

這有助於避免意外將臨時覆蓋提交到版本控制。它還可以更輕鬆地從指令碼生成覆蓋。

pub 工作區中,每個工作區包都可以有一個 pubspec_overrides.yaml 檔案。

最佳實踐

#

積極主動地管理您的依賴項。儘可能確保您的包依賴於最新版本的包。如果您的包依賴於一個過時的包,那麼該過時的包可能又依賴其依賴樹中的其他過時包。過時的包版本可能對應用程式的穩定性、效能和質量產生負面影響。

我們建議以下包依賴最佳實踐。

使用插入符語法

#

使用插入符語法指定依賴項。這允許 pub 工具在包的新版本可用時選擇它們。此外,它還對允許的版本設定了上限。

依賴最新的穩定包版本

#

使用 dart pub upgrade 更新到 pubspec 允許的最新包版本。要識別您的應用或包中未處於最新穩定版本的依賴項,請使用 dart pub outdated

收緊開發依賴的版本約束

#

開發依賴定義了您僅在開發時才需要的包。完成的應用程式不需要這些包。這些包的示例包括測試或程式碼生成工具。將 dev_dependencies 中包的版本約束設定為您的包所依賴的最新版本的下限。

收緊開發依賴的版本約束可能類似於以下內容

yaml
dev_dependencies:
  build_runner: ^2.4.15
  lints: ^5.1.1
  test: ^1.25.15

此 YAML 將 dev_dependencies 設定為最新的補丁版本。

更新包依賴時進行測試

#

如果您執行 dart pub upgrade 而不更新您的 pubspec,API 應該保持不變,並且您的程式碼應該像以前一樣執行——但請務必測試以確保。如果您修改 pubspec 並更新到新的主要版本,那麼您可能會遇到破壞性變更,因此需要更徹底地測試。

使用降級依賴進行測試

#

在開發用於釋出的包時,通常最好允許儘可能廣泛的依賴約束。廣泛的依賴約束減少了包使用者面臨版本解析衝突的可能性。

例如,如果您依賴 foo: ^1.2.3 並且釋出了 foo1.3.0 版本,那麼保留現有依賴約束 (^1.2.3) 可能是合理的。但如果您的包開始使用在 1.3.0 中新增的功能,那麼您將需要將約束提升到 ^1.3.0

然而,當需要提升依賴約束時,很容易忘記。因此,最佳實踐是在釋出之前針對降級依賴測試您的包。

要針對降級依賴進行測試,請執行 dart pub downgrade 並驗證您的包在分析時沒有錯誤並透過所有測試:

dart pub downgrade
dart analyze
dart test

使用降級依賴進行測試應與使用最新依賴進行正常測試同時進行。如果需要提升依賴約束,請自行更改它們或使用 dart pub upgrade --tighten 將依賴項更新到最新版本。

驗證已下載包的完整性

#

檢索新依賴項時,使用 --enforce-lockfile 選項以確保提取的包內容與原始存檔的內容匹配。在不修改 lockfile 的情況下,此標誌僅在以下情況下解析新依賴項:

  • pubspec.yaml 滿足要求
  • pubspec.lock 不缺失
  • 包的內容雜湊匹配