在 Dart 生态系统中使用 packages(包)
实现代码的共享,比如一些 library 和工具。本文旨在介绍如何创建和发布一个 package。
通常来讲,我们所说的 package 一般都是指 library package
,即可以被其他的 package 所依赖,同时它自身也可以依赖其他 package。本文中说的 package 也都默认是指 library package
。
1.package 的组成
下图展示了最简单的 library package 布局:
- library package 中需要包括
pubspec.yaml 文件
和lib 目录
。 - library 的
pubspec.yaml
文件和应用程序的pubspec.yaml
没有本质区别。 - library 的代码需要位于
lib 目录
下,且对于其他 package 是公开的
。你可以根据需要在 lib 下创建任意目录。但是如果你创建的目录名是src
的话,会被当做私有目录
,其他 package 不能直接使用。目前一般的做法都是把代码放到lib/src
目录下,然后将需要公开的 API 通过export
进行导出。
2.创建一个 package
假设我们要开发一个叫做 yance
的 package。
2.1 通过 IDE 创建一个 package
我们来看看创建好的一个 package 工程的结构:
可以看到 lib
目录和 pubspec.yaml
文件已经默认给我们创建好了。
2.2 认识 main library
我们打开 lib
目录,会发现有一个默认和 package 项目名称同名的 dart 文件,我们把这个文件成为 main library
。因为我的 package 名称是 yance
,因此,我的 main library
是 yance.dart
。
main library
的作用是用来声明所有需要公开的 API。
我们打开 yance.dart
文件:
library yance;
/// A Calculator.
class Calculator {
/// Returns [value] plus 1.
int addOne(int value) => value + 1;
}
第一行使用 library
关键字。这个 library 是用来为当前的 package 声明一个唯一标识。也可以不声明 library,在不声明 library 的情况下,package 会根据当前的路径及文件生成一个唯一标记。
如果你需要为当前的 package 生成 API 文档,那么必须声明 library。
至于 library 下面的 Calculator
代码只是一个例子,可以删除。
前面说了 main library
的作用是用来声明公开的 API,下面我们来演示一下,如何声明。
2.3 在 main library 中公开 API
我们在 lib 目录下新建一个 src 目录,后面所有的 yance
package 的实现代码都统一放在 src 目录下,记住,src 下的所有代码都是私有的,其他项目或者 package 不能直接使用。
我们在 src 目录下,创建一个 yance_utils.dart
文件,在里面简单写一点测试代码:
class YanceUtils {
/// Returns [value] plus 1.
int addOne(int value) => value + 1;
}
好了,现在需求来了,我要将 YanceUtils 这个工具类声明为一个公开的 API ,好让其他项目或者 package 可以使用。
那么就需要在 yance.dart
这个 main library
中使用 export
关键字进行声明,格式为:
export 'src/xxx.dart';
输入 src 关键字,然后选择 src/
这个路径:
然后再输入 yance_utils.dart
即可:
library yance;
export 'src/yance_utils.dart';
这样就完成了 API 的公开,yance_utils.dart
里面所有的内容,都可以被其他项目所引用:
import 'package:yance/yance.dart';
class MyDemo{
void test() {
var yanceUtils = YanceUtils();
var addOne = yanceUtils.addOne(1);
print('结果:$addOne}');
}
}
此时,可能大家会有个疑问,使用 export 'src/xxx.dart'
的方式,会将该 dart 文件里所有的内容都完全公开,那假如该文件里的内容,我只想公开一部分,该如何操作呢?
需要使用到 show
关键字:
export 'src/xxx.dart' show 需要公开的类名or方法名or变量名
/// 多个公开的 API 用逗号分隔开
还是以 yance_utils.dart
为例子,我们在 yance_utils.dart
再添加一点代码:
String yanceName = "123";
void yanceMain() {
print('调用了yanceMain方法');
}
class YanceUtils {
/// Returns [value] plus 1.
int addOne(int value) => value + 1;
}
class StringUtils {
String getStr(String value) => value.replaceAll("/", "_");
}
此时,我想公开 yanceName 属性
、yanceMain() 方法
、YanceUtils 类
,可以这样声明:
library yance;
export 'src/yance_utils.dart' show YanceUtils, yanceName, yanceMain;
使用 show
不仅可以避免导出过多的 API,而且可以为开发者提供公开的 API 的概览。
3.发布一个 package
开发完成自己的 package 后,就可以将其发布到 pub.dev 上了。
发布 package 大致需要 5
个步骤:
下面会一一解答每一个步骤。
3.1 关于 pub.dev
的一些政策说明
- 发布是永久的
只要你在 pub.dev
上发布了你的 package,那么它就是永久存在,不会允许你删除它。这样做的目的是为了保护依赖了你 package 的项目,因为你的删除操作会给他们的项目带来破坏。
- 可以随时发布 package 的新版本,而旧版本对未升级的用户仍然可用。
- 对于那些已经发布,但不再维护的 package,你可以把它标记为终止(discontinued)。
进入到 package 页面上的 Admin
标签栏,可以将 package 标记为终止。
标记为终止(discontinued)的 package,以前发布的版本依然留存在 pub.dev 上,并可以被看到,但是它有一个清楚的 终止
徽章,而且不会出现在搜索结果中。
3.2 发布前的准备
3.2.1 首先需要一个 Google 账户
Google 账户申请地址:传送门
如果之前你登录过任何 Google 产品(例如 Gmail、Google 地图或 YouTube),这就意味着你已拥有 Google 帐号。你可以使用自己创建的同一组用户名和密码登录任何其他 Google 产品。
3.2.2 检查 LICENSE 文件
package 必须包含一个 LICENSE 文件。推荐使用 BSD 3-clause 许可证,也就是 Dart 和 Flutter 团队所使用的开源许可证。
参考:
Copyright 2021 com.yance. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3.2.3 检查包大小
通过 gzip
压缩后,你的 package 必须小于 100 MB
。
如果它所占空间过大,考虑将它分割为几个小的 package。或者使用 .pubignore
移除不需要的文件,或者减少包含资源或实例的数量。
3.2.4 检查依赖项
package 应该尽量只依赖于托管在 pub.dev 上的库,以避免不必要的风险。
3.3 编写几个重要的文件 🔺
3.3.1 README.md
README.md
的内容在 pub.dev 上会当做一个页面进行展示:
3.3.2 CHANGELOG.md
如果你的 package 中有 CHANGELOG.md
文件,同样会被作为一个页面(Changelog)进行展示:
来看一个例子:
# 1.0.1
* Fixed missing exclamation mark in `sayHi()` method.
# 1.0.0
* **Breaking change:** Removed deprecated `sayHello()` method.
* Initial stable release.
## Upgrading from 0.1.x
Change all calls to `sayHello()` to instead be to `sayHi()`.
# 0.1.1
* Deprecated the `sayHello()` method; use `sayHi()` instead.
# 0.1.0
* Initial development release.
3.3.3 pubspec.yaml
pubspec.yaml
文件被用于填写关于 package 本身的细节,例如它的描述,主页等等。这些信息将被展现在页面的右侧。
一般来说,需要填写这些信息:
注意:
目前 author
信息已经不需要了,所以大家可以把 author
给删除掉。
3.4 预发布
预发布使用如下命令。执行预发布命令不会真的发布,它可以帮助我们验证填写的发布信息是否符合 pub.dev 的规范,同时展示所有会发布到 pub.dev 的文件。
dart pub publish --dry-run
比如,我运行的结果是:
chenyouyu@chenyouyudeMacBook-Pro-2 yance % dart pub publish --dry-run
Publishing yance 0.0.1 to https://pub.dartlang.org:
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- lib
| |-- src
| | '-- yance_utils.dart
| '-- yance.dart
|-- pubspec.yaml
|-- test
| '-- yance_test.dart
'-- yance.iml
Package validation found the following potential issue:
* Your pubspec.yaml includes an "author" section which is no longer used and may be removed.
Package has 1 warning.
它提示我们author
信息已经不需要了,可以删除。
删除后,再次运行就没有警告了。
3.5 正式发布
当你已经准备好正式发布你的 package 后,移除 —dry-run 参数:
dart pub publish
点击链接会跳转浏览器验证账户,验证成功后,会有提示:
账户验证通过后,会继续执行上传任务:
此时,去 pub.dev 上就能看到发布成功的 package 了:
pub.dev 会检测 package 支持哪些平台,并呈现到 package 的页面上。
注意:
正式发布可能需要科学上网。