创建包
Dart 生态系统使用 包 来共享库和工具等软件。此页面将告诉您如何创建标准的共享 包。
创建新包
#要为包创建初始目录和结构,请使用 dart create
命令和 package
模板。
$ dart create -t package <PACKAGE_NAME>
包的组成
#下图显示了包的最简单布局
库的最低要求是
- 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:io
或 dart:js_interop
的单独库。某些包具有单独的库,这些库旨在在主库不是的情况下使用前缀导入。
让我们看一下实际包的组织结构:shelf。 shelf 包提供了一种使用 Dart 创建 Web 服务器的简单方法,其布局结构通常用于 Dart 包。
直接在 lib 下,主库文件 shelf.dart
从 lib/src
中的多个文件导出 API。为了避免公开超出预期的 API,并使开发人员能够概述包的整个公共 API,shelf.dart
使用 show
来指定要导出的确切符号
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。
import 'package:utilities/utilities.dart';
从您自己的包导入库文件时,如果两个文件都位于 lib 内部,或者两个文件都位于 lib 外部,请使用相对路径。当导入的文件在 lib 中,而导入器在外部时,请使用 package:
。
下图显示了如何从 lib 和 web 导入 lib/foo/a.dart
。
有条件地导入和导出库文件
#如果您的库支持多个平台,那么您可能需要有条件地导入或导出库文件。常见的用例是支持 Web 和原生平台的库。
要进行有条件的导入或导出,您需要检查是否存在 dart:*
库。这是一个有条件导出代码的示例,该代码检查是否存在 dart:io
和 dart:js_interop
export 'src/hw_none.dart' // Stub implementation
if (dart.library.io) 'src/hw_io.dart' // dart:io implementation
if (dart.library.js_interop) 'src/hw_web.dart'; // package:web implementation
以下是代码的作用
- 在可以使用
dart:io
的应用中(例如,命令行应用),导出src/hw_io.dart
。 - 在可以使用
dart:js_interop
的应用中(Web 应用),导出src/hw_web.dart
。 - 否则,导出
src/hw_none.dart
。
要有条件地导入文件,请使用与上面相同的代码,但将 export
更改为 import
。
所有条件导出的库都必须实现相同的 API。例如,这是 dart:io
的实现
import 'dart:io';
void alarm([String? text]) {
stderr.writeln(text ?? message);
}
String get message => 'Hello World from the VM!';
这是默认实现,它使用抛出 UnsupportedError
的存根
void alarm([String? text]) => throw UnsupportedError('hw_none alarm');
String get message => throw UnsupportedError('hw_none message');
在任何平台上,您都可以导入具有条件导出代码的库
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.md
和 CHANGELOG.md
)在 发布包中进行了描述。有关如何组织包目录的更多信息,请参阅 pub 包布局约定。
为库编写文档
#您可以使用 dart doc
工具为库生成 API 文档。 dart doc
解析源代码以查找使用 ///
语法的文档注释
/// The event handler responsible for updating the badge in the UI.
void updateBadge() {
...
}
有关生成的文档的示例,请参阅 shelf 文档。
要在生成的文档中包含任何库级别文档,请添加一个 library
指令并将注释直接附加在其上方。有关记录库的原因和方法,请参阅有效的 Dart:文档。
分发开源库
#如果您的库是开源的,我们建议在 pub.dev 站点上共享它。要发布或更新库,请使用 pub publish,它会上传您的包并创建或更新其页面。例如,请参阅 shelf 包的页面。有关如何准备要发布的包的详细信息,请参阅发布包。
pub.dev 站点不仅托管您的软件包,还会生成并托管您软件包的 API 参考文档。指向最新生成文档的链接位于软件包的 关于 框中;例如,请参阅 shelf 软件包的 API 文档。指向之前版本文档的链接位于软件包页面的 版本 选项卡中。
为确保您软件包的 API 文档在 pub.dev 站点上看起来良好,请按照以下步骤操作
- 在发布您的软件包之前,运行
dart doc
工具,以确保您的文档成功生成并且看起来符合预期。 - 发布您的软件包后,检查 版本 选项卡,以确保文档成功生成。
- 如果文档完全没有生成,请点击 版本 选项卡中的 失败 以查看
dart doc
的输出。
资源
#使用以下资源了解有关软件包的更多信息
- 库和导入涵盖了库文件的使用。
- 软件包 文档很有用,特别是 软件包布局约定。
- 不应提交的内容涵盖了不应检入源代码存储库的内容。
- dart-lang 组织下的较新软件包往往展示了最佳实践。请考虑研究以下示例:dart_style、path、shelf、source_gen 和 test。
除非另有说明,本网站上的文档反映了 Dart 3.6.0。页面上次更新于 2024-12-10。 查看源文件 或 报告问题。