Flutter:创建和发布一个 Dart Package

简介: 在 Dart 生态系统中使用 packages(包) 实现代码的共享,比如一些 library 和工具。本文旨在介绍如何创建和发布一个 package。

在 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 libraryyance.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 的页面上。

注意:

正式发布可能需要科学上网。

相关文章
|
2月前
|
Dart
如何在 Flutter 项目中使用 Dart 语言?
如何在 Flutter 项目中使用 Dart 语言?
127 58
|
22天前
|
Dart
flutter dart mixin 姿势
flutter dart mixin 姿势
|
1月前
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
30 12
|
6月前
|
前端开发 C++ 容器
Flutter-完整开发实战详解(一、Dart-语言和-Flutter-基础)(1)
Flutter-完整开发实战详解(一、Dart-语言和-Flutter-基础)(1)
|
3月前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
78 4
Flutter&Dart-异步编程Future、Stream极速入门
|
3月前
|
Dart JavaScript 前端开发
Dart或Flutter中解决异常-type ‘int‘ is not a subtype of type ‘double‘
Dart或Flutter中解决异常-type ‘int‘ is not a subtype of type ‘double‘
135 4
|
3月前
|
Dart
Flutter笔记:手动配置VSCode中Dart代码自动格式化
Flutter笔记:手动配置VSCode中Dart代码自动格式化
464 5
|
4月前
|
JSON Dart 安全
Flutter Dart Macro 宏简化 JSON 序列化
今天我们将会体验 dart 语言新特性 macro 宏,来实现对 json 的序列化,用到的包是官方实验室写的 json 包。 本文将会一步步的带你实现这个功能,那我们开始吧。
Flutter Dart Macro 宏简化 JSON 序列化
|
3月前
|
Dart 开发工具 Android开发
Android Studio导入Flutter项目提示Dart SDK is not configured
Android Studio导入Flutter项目提示Dart SDK is not configured
305 4
|
3月前
|
Dart 安全 API
Android跨平台开发之Dart 3.5 与 Flutter 3.24:革新跨平台应用开发
【Dart 3.5 与 Flutter 3.24:革新跨平台应用开发】首发于公众号“AntDream”。本文深度解析 Dart 3.5 和 Flutter 3.24 的新特性,包括空安全强化、Web 与原生互操作性增强及 Flutter GPU API 等,展示了如何提升代码质量和用户体验。
63 1