目录

包布局约定

构建 pub 包 时,我们鼓励您遵循本页描述的约定。它们描述了如何组织包中的文件和目录,以及如何命名。

这是一个完整的包(名为 enchilada ),它使用了这些指南的各个方面:

enchilada/
  .dart_tool/ *
  pubspec.yaml
  pubspec.lock **
  LICENSE
  README.md
  CHANGELOG.md
  benchmark/
    make_lunch.dart
  bin/
    enchilada
  doc/
    api/ ***
    getting_started.md
  example/
    main.dart
  hook/
    build.dart
  integration_test/
    app_test.dart
  lib/
    enchilada.dart
    tortilla.dart
    guacamole.css
    src/
      beans.dart
      queso.dart
  test/
    enchilada_test.dart
    tortilla_test.dart
  tool/
    generate_docs.dart
  web/
    index.html
    main.dart
    style.css

* 运行 dart pub get 后, .dart_tool/ 目录就会存在。不要将其检入源代码控制。 更多信息,请参见 工具的项目特定缓存

** 运行 dart pub get 后, pubspec.lock 文件就会存在。除非您的包是 应用程序包 ,否则不要将其添加到源代码管理中。

*** 运行 dart doc 后, doc/api 目录会在本地存在。不要将 api 目录检入源代码控制。

pubspec 文件

#
enchilada/
  pubspec.yaml
  pubspec.lock

每个包都有一个 pubspec ,这是一个名为 pubspec.yaml 的文件,位于包的根目录中。这就是使它成为一个包的原因。

在包上运行 dart pub getdart pub upgradedart pub downgrade 会创建一个名为 pubspec.lock锁文件 。如果您的包是 应用程序包 ,请将锁文件检入源代码控制。否则,不要检入。

更多信息,请参见 pubspec 页面

LICENSE 文件

#
enchilada/
  LICENSE

如果您要发布您的包,请包含一个名为 LICENSE 的许可证文件。我们建议使用 OSI 批准的许可证 ,例如 BSD-3-Clause ,以便其他人可以重用您的作品。

README.md 文件

#
enchilada/
  README.md

开源项目中非常常见的一个文件是_README_文件,它描述了项目。这在 pub 中尤其重要。当您上传到 pub.dev 网站 时,您的 README.md 文件将显示在您的包页面上——以 Markdown 渲染。这是向人们介绍您的代码的理想场所。

有关如何撰写优秀的 README 的指南,请参见 撰写包页面

CHANGELOG.md 文件

#
enchilada/
  CHANGELOG.md

包含一个 CHANGELOG.md 文件,其中包含包的每个版本的章节,并包含帮助包用户升级的说明。包的用户经常查看变更日志以发现错误修复和新功能,或者确定升级到包的最新版本需要多少工作量。

为了支持解析 CHANGELOG.md 的工具,请使用以下格式:

  • 每个版本都有自己的部分,带有标题。
  • 版本标题级别均为 1 级或 2 级。
  • 版本标题文本包含包版本号,前面可以选择添加“v”。

当您将包上传到 pub.dev 网站 时,您的包的 CHANGELOG.md 文件(如果有)将显示在 变更日志 选项卡中,并以 Markdown 渲染。

这是一个 CHANGELOG.md 文件的示例。如示例所示,您可以添加子部分。

markdown
# 1.0.1

* 已修复 `sayHi()` 方法中缺少感叹号的错误。

# 1.0.0

* **重大更改:** 已删除已弃用的 `sayHello()` 方法。
* 初始稳定版本。

## 从 0.1.x 升级

将所有对 `sayHello()` 的调用更改为对 `sayHi()` 的调用。

# 0.1.1

* 已弃用 `sayHello()` 方法;请改用 `sayHi()`

# 0.1.0

* 初始开发版本。

公共目录

#

包中的两个目录对其他包是公开的: libbin 。您将 公共库 放在 lib 中,将 公共工具 放在 bin 中。

公共库

#

以下目录结构显示了 enchilada 的 lib 部分:

enchilada/
  lib/
    enchilada.dart
    tortilla.dart

许多 定义了其他包可以导入和使用的 Dart 库。这些公共 Dart 库文件位于名为 lib 的目录中。

大多数包定义单个库,用户可以导入它。在这种情况下,它的名称通常应与包的名称相同,例如此示例中的 enchilada.dart 。但是您也可以定义其他库,其名称对您的包有意义。

这样做时,用户可以使用包的名称和库文件导入这些库,如下所示:

dart
import 'package:enchilada/enchilada.dart';
import 'package:enchilada/tortilla.dart';

如果您想组织公共库,您也可以在 lib 中创建子目录。如果您这样做,用户将在导入时指定该路径。假设您有以下文件层次结构:

enchilada/
  lib/
    some/
      path/
        olives.dart

用户如下导入 olives.dart

dart
import 'package:enchilada/some/path/olives.dart';

请注意, lib 中只能包含 入口点(包含 main() 函数的 Dart 脚本)不能放在 lib 中。如果您将 Dart 脚本放在 lib 中,您会发现它包含的任何 package: 导入都无法解析。相反,您的入口点应该放在适当的 入口点目录 中。

有关包的更多信息,请参见 创建包

公共工具

#

放在 bin 目录中的 Dart 脚本是公开的。如果您在包的目录中,您可以使用 dart run 运行来自包所依赖的任何其他包的 bin 目录中的脚本。从 任何 目录,您可以 运行脚本 来自您使用 dart pub global activate 激活的包。

如果您打算让其他包依赖您的包,并且您希望您的脚本对您的包私有,请将它们放在顶层 tool 目录中。如果您不打算让其他包依赖您的包,您可以将脚本留在 bin 中。

公共资源

#
enchilada/
  lib/
    guacamole.css

虽然大多数包的存在是为了让您重用 Dart 代码,但您也可以重用其他类型的內容。例如, Bootstrap 的包可能会包含许多 CSS 文件供包的使用者使用。

这些文件位于顶层 lib 目录中。您可以将任何类型的文件放在那里,并根据需要使用子目录对其进行组织。

实现文件

#
enchilada/
  lib/
    src/
      beans.dart
      queso.dart

lib 内的库是公开可见的:其他包可以自由地导入它们。但是,包的大部分代码是内部实现库,只应由包本身导入和使用。这些库位于名为 srclib 子目录中。如果它有助于您组织内容,您可以在其中创建子目录。

您可以从同一 中的其他 Dart 代码(例如 lib 中的其他库、 bin 中的脚本和测试)中导入位于 lib/src 中的库,但您永远不应该从另一个包的 lib/src 目录中导入。这些文件不是包的公共 API 的一部分,它们可能会以可能破坏您代码的方式发生更改。

从您自己的包中导入库的方式取决于库的位置:

例如:

lib/beans.dart
dart
// 从 lib 内部导入时:
import 'src/beans.dart';
test/beans_test.dart
dart
// 从 lib 外部导入时:
import 'package:enchilada/src/beans.dart';

您在此处使用的名称(在本例中为 enchilada )是您在其 pubspec 中为包指定的名称。

Web 文件

#
enchilada/
  web/
    index.html
    main.dart
    style.css

对于 Web 包,请将入口点代码(包含 main() 的 Dart 脚本和支持文件,例如 CSS 或 HTML)放在 web 下。如果需要,您可以将 web 目录组织成子目录。

库代码 放在 lib 下。如果库没有被 web 下的代码或其他包直接导入,请将其放在 lib/src 下。将 基于 Web 的示例 放在 example 下。有关将资源(例如图像)放在何处的提示,请参见 公共资源

命令行应用程序

#
enchilada/
  bin/
    enchilada

某些包定义可以直接从命令行运行的程序。这些可以是 shell 脚本或任何其他脚本语言,包括 Dart。

如果您的包定义了这样的代码,请将其放在名为 bin 的目录中。如果您使用 dart pub global 设置它,则可以从命令行的任何位置运行该脚本。

测试和基准测试

#
enchilada/
  test/
    enchilada_test.dart
    tortilla_test.dart

每个包都应该有测试。使用 pub 时,约定是这些测试大部分放在 test 目录中(或者如果您愿意,也可以放在其中的某个目录中),并且文件名的末尾带有 _test

通常,这些测试使用 test 包。

enchilada/
  integration_test/
    app_test.dart

Flutter 应用包也可能有一些特殊的集成测试,这些测试使用 integration_test 包。这些测试位于它们自己的 integration_test 目录中。

其他包可能会选择遵循类似的模式,以将其较慢的集成测试与单元测试分开,但请注意,默认情况下, dart test 不会运行这些测试。您必须使用 dart test integration_test 显式运行它们。

enchilada/
  benchmark/
    make_lunch.dart

具有性能关键代码的包也可能包含 基准测试 。这些测试不是测试 API 的正确性,而是测试其速度(或内存使用情况,或者可能是其他经验指标)。

文档

#
enchilada/
  doc/
    api/
    getting_started.md

如果您有代码和测试,那么您可能需要做的下一件事就是

良好的文档也是必不可少的。这些文档放在名为 doc 的目录中。

运行 dart doc 工具时,它默认情况下会将 API 文档放在 doc/api 下。由于 API 文档是从源代码生成的,因此您不应将其放在源代码控制下。

除了生成的 api 之外,我们对您编写的文档的格式或组织没有任何指导。使用您喜欢的任何标记格式。

示例

#
enchilada/
  example/
    main.dart

代码、测试、文档,还有什么您的用户可能需要呢?当然还有使用您包的独立示例程序!这些程序放在 example 目录中。如果示例很复杂并且使用了多个文件,请考虑为每个示例创建一个目录。否则,您可以将每个示例直接放在 example 中。

在您的示例中,使用 package: 从您自己的包中导入文件。这确保了您包中的示例代码看起来与包外部的代码完全一样。

如果您可能要发布您的包,请考虑创建一个名称为以下名称之一的示例文件:

  • example/example[.md]
  • example[/lib]/main.dart
  • example[/lib]/package_name.dart
  • example[/lib]/package_name_example.dart
  • example[/lib]/example.dart
  • example/README[.md]

当您发布包含上述一个或多个文件的包时,pub.dev 网站会创建一个 示例 选项卡来显示它找到的第一个文件(按上述列表中显示的顺序搜索)。例如,如果您的包在其 example 目录下有很多文件,包括一个名为 README.md 的文件,那么您的包的示例选项卡将显示 example/README.md 的内容(作为 Markdown 解析)。

内部工具和脚本

#
enchilada/
  tool/
    generate_docs.dart

成熟的包通常有一些小的辅助脚本和程序,开发人员在开发包本身时会运行这些脚本和程序。例如测试运行器、文档生成器或其他一些自动化工具。

bin 中的脚本不同,这些脚本 适用于包的外部用户。如果您有任何这些脚本,请将它们放在名为 tool 的目录中。

钩子

#
enchilada/
  hook/
    build.dart

包可以定义由 Dart 和 Flutter SDK 调用的钩子。这些钩子具有预定义的 CLI,如果存在,将由 SDK 工具调用。

由于这些钩子在运行和构建时由 dartflutter 工具调用,因此这些钩子的依赖项必须是普通依赖项,而不是 dev_dependencies

工具的项目特定缓存

#

.dart_tool/ 目录在运行 dart pub get 时创建,并且可能随时被删除。各种工具使用此目录来缓存特定于您的项目和/或本地机器的文件。 .dart_tool/ 目录永远不应检入源代码控制或在机器之间复制。

删除 .dart_tool/ 目录通常也是安全的,尽管某些工具可能需要重新计算缓存的信息。

示例:dart pub get 工具将依赖项下载并提取到全局 $PUB_CACHE 目录中,然后编写一个 .dart_tool/package_config.json 文件,将 包名称 映射到全局 $PUB_CACHE 目录中的目录。 .dart_tool/package_config.json 文件由其他工具使用,例如分析器和编译器,当它们需要解析诸如 import 'package:foo/foo.dart' 之类的语句时。

在开发需要项目特定缓存的工具时,您可以考虑使用 .dart_tool/ 目录,因为大多数用户已经使用 .gitignore 忽略了它。当为用户 .dart_tool/ 目录中的工具缓存文件时,应使用唯一的子目录。为了避免冲突,形式为 .dart_tool/<tool_package_name>/ 的子目录保留给名为 <tool_package_name> 的包。如果您的工具不是通过 pub.dev 网站 分发的,您可以考虑发布一个占位符包以保留唯一名称。

示例:package:build 提供了一个用于编写代码生成步骤的框架。运行这些构建步骤时,文件将缓存在 .dart_tool/build/ 中。这有助于加快将来重新运行构建步骤的速度。