目录

创建包

Dart 生态系统使用 来共享软件,例如库和工具。此页面介绍如何创建一个标准的共享

创建新的包

#

要创建包的初始目录和结构,请使用 dart create 命令和 package 模板:

$ dart create -t package <PACKAGE_NAME>

包的构成

#

下图显示了包的最简单布局:

根目录包含 pubspec.yaml 和 lib/file.dart

库的最低要求是:

pubspec 文件
库的 pubspec.yaml 文件与 应用程序包 的相同——没有特殊的标识来指示该包是库。
lib 目录
正如您可能预期的那样,库代码位于 lib 目录下,并且对其他包是公开的。您可以根据需要在 lib 下创建任何层次结构。按照惯例,实现代码放在 lib/src 下。lib/src 下的代码被认为是私有的;其他包永远不需要导入 src/... 。要使 lib/src 下的 API 公开,您可以从直接位于 lib 下的文件导出 lib/src 文件。

包的组织

#

当您创建小的、独立的库(称为 小型库 )时,包最易于维护、扩展和测试。在大多数情况下,每个类都应该在其自己的小型库中,除非您遇到两个类紧密耦合的情况。

直接在 lib 下创建一个“主”库文件, lib/<package-name>.dart ,它导出所有公共 API。这允许用户通过导入单个文件来获得库的所有功能。

lib 目录还可以包含其他可导入的非 src 库。例如,您的主库可能跨平台工作,但您创建了依赖于 dart:iodart:js_interop 的单独库。有些包有单独的库,当主库不存在时,这些库需要使用前缀导入。

让我们看看一个真实世界包的组织:shelf。 shelf 包提供了一种使用 Dart 创建 Web 服务器的简单方法,其布局是 Dart 包常用的结构:

shelf 根目录包含 example、lib、test 和 tool 子目录

直接在 lib 下,主库文件 shelf.dartlib/src 中的多个文件导出 API。为了避免暴露超出预期的 API——并为开发人员提供整个包的公共 API 概述—— shelf.dart 使用 show 精确指定要导出的符号:

lib/shelf.dart
dart
export 'src/cascade.dart' show Cascade;
export 'src/handler.dart' show Handler;
export 'src/hijack_exception.dart' show HijackException;
export 'src/middleware.dart' show Middleware, createMiddleware;
export 'src/middleware/add_chunked_encoding.dart' show addChunkedEncoding;
export 'src/middleware/logger.dart' show logRequests;
export 'src/middleware_extensions.dart' show MiddlewareExtensions;
export 'src/pipeline.dart' show Pipeline;
export 'src/request.dart' show Request;
export 'src/response.dart' show Response;
export 'src/server.dart' show Server;
export 'src/server_handler.dart' show ServerHandler;

shelf 包还包含一个小型库:shelf_io。此适配器处理来自 dart:io 的 HttpRequest 对象。

导入库文件

#

从另一个包导入库文件时,使用 package: 指令指定该文件的 URI。

dart
import 'package:utilities/utilities.dart';

从您自己的包导入库文件时,如果两个文件都在 lib 内部,或者两个文件都在 lib 外部,则使用相对路径。当导入的文件在 lib 中而导入者在外部时,使用 package:

下图显示了如何从 lib 和 web 导入 lib/foo/a.dart

lib/bar/b.dart 使用相对导入;web/main.dart 使用包导入

有条件地导入和导出库文件

#

如果您的库支持多个平台,那么您可能需要有条件地导入或导出库文件。一个常见的用例是支持 Web 和原生平台的库。

要进行有条件的导入或导出,您需要检查 dart:* 库的存在。这是一个有条件导出代码的示例,该代码检查 dart:iodart:js_interop 的存在:

lib/hw_mp.dart
dart
export 'src/hw_none.dart' // 存根实现
    if (dart.library.io) 'src/hw_io.dart' // dart:io 实现
    if (dart.library.js_interop) 'src/hw_web.dart'; // package:web 实现

这段代码的作用如下:

  • 在可以使用 dart:io 的应用程序中(例如,命令行应用程序),导出 src/hw_io.dart
  • 在可以使用 dart:js_interop 的应用程序中(Web 应用程序),导出 src/hw_web.dart
  • 否则,导出 src/hw_none.dart

要根据条件导入文件,请使用与上述相同的代码,但将 export 更改为 import

所有有条件导出的库都必须实现相同的 API。例如,这是 dart:io 实现:

lib/src/hw_io.dart
dart
import 'dart:io';

void alarm([String? text]) {
  stderr.writeln(text ?? message);
}

String get message => 'Hello World from the VM!';

这是默认实现,它使用抛出 UnsupportedError 的存根:

lib/src/hw_none.dart
dart
void alarm([String? text]) => throw UnsupportedError('hw_none alarm');

String get message => throw UnsupportedError('hw_none message');

在任何平台上,您都可以导入具有条件导出代码的库:

dart
import 'package:hw_mp/hw_mp.dart';

void main() {
  print(message);
}

提供其他文件

#

精心设计的包易于测试。我们建议您使用 test 包编写测试,并将测试代码放在包顶部的 test 目录中。

如果您创建任何旨在供公众使用的命令行工具,请将它们放在公共的 bin 目录中。使用 dart pub global activate 启用从命令行运行工具。在pubspec的 executables 部分 中列出该工具,允许用户直接运行它,而无需调用 dart pub global run

如果您包含如何使用库的示例会很有帮助。这将进入包顶部的 example 目录。

在开发过程中创建的任何不供公众使用的工具或可执行文件都放在 tool 目录中。

如果您将库发布到 pub.dev 站点,则需要其他文件,例如 README.mdCHANGELOG.md ,这些文件在 发布包 中进行了描述。有关如何组织包目录的更多信息,请参阅 pub 包布局约定

文档化库

#

您可以使用 dart doc 工具为库生成 API 文档。 dart doc 解析源代码以查找 文档注释 ,这些注释使用 /// 语法:

dart
/// 负责更新 UI 中徽章的事件处理程序。
void updateBadge() {
  ...
}

有关生成的文档示例,请参阅 shelf 文档。

要在生成的文档中包含任何 库级 文档,请添加 library 指令并将注释直接附加在其上方。有关文档化库的如何以及为何,请参阅 Effective Dart:文档

分发开源库

#

如果您的库是开源的,我们建议您在 pub.dev 网站 上共享它。要发布或更新库,请使用 pub publish ,它将上传您的包并创建或更新其页面。例如,请参阅 shelf 包 的页面。有关如何准备包以进行发布的详细信息,请参阅 发布包

pub.dev 网站不仅托管您的包,还生成和托管您包的 API 参考文档。包的“关于”框中包含指向最新生成的文档的链接;例如,请参阅 shelf 包的 API 文档。 包页面的“版本”选项卡中包含指向先前版本文档的链接。

要确保您的包的 API 文档在 pub.dev 网站上看起来不错,请按照以下步骤操作:

  • 在发布包之前,运行 dart doc 工具以确保您的文档成功生成并按预期显示。
  • 发布包后,检查“版本”选项卡以确保文档已成功生成。
  • 如果文档根本没有生成,请单击“版本”选项卡中的“失败”以查看 dart doc 输出。

资源

#

使用以下资源来了解有关包的更多信息: