Flutter学习|Flutter工程代码管理 pubspec.yaml、.packages 与 pubspec.lock文件的来龙去脉

? 上一篇文章中,我们基本上了解了Flutter APP和Flutter Module的构建流程,本文主要是通过pubspec.yaml,.packages,pubspec.lock三个文件为切入点,一起了解在 Flutter 中如何通过配置文件来管理工程代码依赖
首先直接简单介绍总结下这三个文件的作用

  1. pubspec.yaml
    Dart包的配置文件,管理 Flutter 工程代码的依赖,比如第三方库、Dart 运行环境、Flutter SDK 版本都可以通过它来进行统一管理。所以,pubspec.yaml 与 iOS 中的 Podfile、Android 中的 build.gradle、前端的 package.json 在功能上是类似的
  2. .packages
    完成了所有依赖包的下载后自动创建,将依赖的包名与系统缓存中的包文件路径进行映射,方便后续维护
  3. pubspec.lock
    自动创建 pubspec.lock 文件,pubspec.lock 文件的作用类似 iOS 的 Podfile.lock 或前端的 package-lock.json 文件,用于记录当前状态下实际安装的各个直接依赖、间接依赖的包的具体来源和版本号。
接下来,主要分享在 Flutter 中如何通过配置文件来管理工程代码依赖
包管理工具Pub
Dart提供了包管理工具Pub,用于管理代码,资源,版本。Dart 生态系统使用包来管理共享软件,比如:库和工具。我们使用Pub包管理工具 来获取Dart包。在Pub上,可以找到公开可用的包。或者从本地文件系统或其他的位置,比如Git仓库,加载可用的包。无论包是从什么途径加载的, Pub 都会进行版本依赖管理,从而帮助我们获得版本兼容的软件包以及SDK。类似于Android 中的 JCenter/Maven、iOS 中的 CocoaPods、前端中的 npm 库。
Pub工具包含管理 Package 、部署 Package 和部署命令行应用的命令。
在Dart中库和应用都属于包。pubspec.yaml是包的配置文件,包含了元数据(包的名称,版本),运行环境(DartSDK,FlutterSDK版本),外部依赖,内部配置(资源管理等)。每一个Dart包目录中至少包含一个pubspec文件。
下面我们一起来看下 pubspec.yaml文件详细介绍:
name: hello_flutter# 应用名称 description: A new Flutter project. # 应用描述# 指定生成发布包的位置 # 非必填 # 若不填写,则默认使用pub.dev站点进行发布,但若希望阻止发布,则需要声明为none。 # 同时此设置可以将flutter项目发布到自定义的服务器之中。publish_to: 'none'version: 1.0.0+11 # 应用版本信息,版本为1.0.0,版本编码versionCode为11# 项目描述,非必填 # 若需要将项目托管在pub.dev则该字段必填。 description: >- Have you been turned into a newt?Would you like to be? This package can help. It has all of the newt-transmogrification functionality you have been looking for. # 项目主页,非必填 # 该项目的介绍主页,填写域名 homepage: https://example-pet-store.com/newtify# 开发文档位置,非必填 # 与`homepage`不同,若该项目还包含其他文档,可以将文档的地址添加到该节点下。如果项目托管在pub.dev,该节点显示项目的API信息。 documentation: https://example-pet-store.com/newtify/docs# 问题追踪页面,非必填 # 若该项目是一个开源且随时更新的项目,可以通过填写该属性,标明该项目的问题追踪文档站点,如果使用pub.dev来进行项目托管,则pub.dev将尝试通过该字段显示该项目的问题跟踪链接。若该项目托管在github,则可以将该字段填写为github的issues issue_tracker: https://github.com///issues# Dart的运行环境(支持>=2.7到<3.0区间) environment: sdk: ">=2.7.0 <3.0.0"# 项目的第三方插件依赖,在这个标签中列出了该项目正常工作所需的每一个软件包与版本。以下通过实例详解该标签的详情 dependencies: # 实例1 直接写明约束版本,若该插件是发布在https://pub.dev/ 之上,IDE会直接在项目目录下执行`flutter packages get`来下载其插件的最新版本 transmogrify: # 实例2 该插件是在实例1的基础上进行延伸,其中`^1.4.0`的含义是约束了版本号,也就是在该项目中,需要使用1.4.0版本 transmogrify: ^1.4.0 #实例3 若该插件未部署在pub.dev之上,则可以通过URL来指定出插件下载的源 transmogrify: hosted: name: transmogrify url: http://some-package-server.com #实例4 基于实例3,其中version表明了使用该插件的版本信息 transmogrify: hosted: name: transmogrify url: http://some-package-server.com version: ^1.4.0 #实例5 若该插件是发布在git上,可以用以下方式来进行插件获取,默认获取master下代码 transmogrify: git: url: git://github.com/munificent/kittens.git #实例6 基于实例5,其中ref标明获取的分支信息 transmogrify: git: url: git://github.com/munificent/kittens.git ref: some-branch #实例7 基于实例5,若插件只是在项目中的某一个目录中,可以通过path来指定插件位置 transmogrify: git: url: git://github.com/munificent/kittens.git path: path/to/kittens #实例8 若插件在本地某一目录,可以通过指定path来找到该插件 transmogrify: path: /Users/me/transmogrify #指定版本,若该项目使用的插件需要约束版本,则方法如下 #实例1 在该项目中,此插件指定版本为1.4.0 transmogrify: ^1.4.0 #实例2 在该项目中,此插件最低版本为1.2.3 transmogrify: ">=1.2.3" #实例3 在该项目中,此插件最低支持2.0.0版本,但不支持3.0.0以上版本 transmogrify: ">=2.0.0 <3.0.0" #实例4 在该项目中,此插件最高支持到1.2.3以下版本 transmogrify: "<1.2.3" #指定Flutter SDK #实例1 项目必填项,指定SDK,并获取SDK最新版 flutter: sdk: flutter #实例2 基于实例1,指定SDK版本号 flutter: sdk: flutter version: ">=2.0.0-dev.68.0 <3.0.0" #实例3 另外一种写法 flutter_driver: sdk: flutter version: ^0.0.1# 区别于dependencies标签,dependencies是生产环境依赖库版本,dev_dependencies是开发环境依赖库版本,该环境仅在开发调试时使用。标签规则同dependencies dev_dependencies: flutter_test: sdk: flutter# 重写依赖包,会强制下载对应依赖包,并可以对该依赖包进行重写。 dependency_overrides: transmogrify: ^1.4.0# 可以将Dart2的可执行脚本引入到flutter之中,作为插件使用,但前提是这些脚本均可以在命令行正常调用。 executables: : # 项目中配置声明方式 # 用于在项目中添加资源、设置字体、配置插件参数等。 flutter: uses-material-design: true # 实例1 添加资源 assets: - images/park.jpg - images/lake.jpg - images/touxiang.jpg#设置字体,样式,可以通过声明family来设置字体分组 fonts: - family: Schyler fonts: - asset: fonts/Schyler-Regular.ttf - asset: fonts/Schyler-Italic.ttf style: italic - family: Trajan Pro fonts: - asset: fonts/TrajanPro.ttf - asset: fonts/TrajanPro_Bold.ttf weight: 700

对于包,我们通常是指定版本区间,而很少直接指定特定版本,因为包升级变化很频繁,如果有其他的包直接或间接依赖这个包的其他版本时,就会经常发生冲突。
而对于运行环境,如果是团队多人协作的工程,建议将 Dart 与 Flutter 的 SDK 环境写死,统一团队的开发环境,避免因为跨 SDK 版本出现的 API 差异进而导致工程问题。
比如,在上面的示例中,我们可以将 Dart SDK 写死为 2.7.0,Flutter SDK 写死为2.0.0。
environment: sdk: 2.7.0flutter: 2.0.0

对于dependencies中不同数据源,Dart会使用不同的方式进行管理,最终都会将远端的包全部下载到本地。比如:对于Git声明依赖的方式,Pub会clone git仓库;对于版本号的方式,Pub则会从pub.dartlang.ort下载包。如果还有其他的依赖包,比如pkg1还包含了pkg2包,Pub也会一并下载。
Pub在下载完所有的依赖包之后,Pub会在应用的更目录下创建.packages文件,并将依赖包名与系统缓存中的包文件路径进行映射,方便后期维护。
最后,Pub会自动创建pubspec.loc文件。pubspec.loc文件的作用就是类似IOS的Podfile.lock或者前端的package-lock.json文件,用于记录当前状态下实际安装的各个直接依赖,间接以来的包的具体来源和版本号。
比较活跃的第三方包的升级通常比较频繁,因此对于多人协作的 Flutter 应用来说,我们需要把 pubspec.lock 文件也一并提交到代码版本管理中,这样团队中的所有人在使用这个应用时安装的所有依赖都是完全一样的,以避免出现库函数找不到或者其他的依赖错误。
除了提供功能和代码维度的依赖之外,包还可以提供资源的依赖。如何资源依赖在上面pubspec.yaml已有介绍:目录文件配置如下
# 项目中配置声明方式 # 用于在项目中添加资源、设置字体、配置插件参数等。 flutter: uses-material-design: true # 实例1 添加资源 assets: - images/park.jpg - images/lake.jpg - images/touxiang.jpg

原生工程如何找到Flutter module
有人在想pub上面的各种插件有些是需要调用原生功能,那么我们在pubspec.yaml引入之后,它又是如何被原生工程发现有啥如何被include到原生工程的呢?
那么这里就需要在介绍两个问题:.flutter-plugins 与 .flutter-plugins-dependencies文件,这两个文件是在flutter pub get之后,也就是pub在下载了第三方引入库之后自动生成的,下面看看这两个文件的主要内容:
.flutter-plugins
# This is a generated file; do not edit or check into version control. connectivity=/Users/beason/Library/Flutter/flutter1.12.13/.pub-cache/hosted/pub.flutter-io.cn/connectivity-0.4.5+7/ image_picker_saver=/Users/beason/Library/Flutter/flutter1.12.13/.pub-cache/hosted/pub.flutter-io.cn/image_picker_saver-0.3.0/ message_core=/Users/beason/Projects/sfim/poc_lanyun/load_module/fs-base-ios-flutter-foundation/message_core/

.flutter-plugins-dependencies
{"_info":"// This is a generated file; do not edit or check into version control.", "dependencyGraph":[ {"name":"connectivity", "dependencies":[] }, {"name":"image_picker_saver", "dependencies":[] }, {"name":"message_core", "dependencies":[] } ] }

.flutter-plugins 主要是记载了所有的插件名称以及插件缓存地址
.flutter-plugins-dependencies 主要记载了所有插件名称以及它们之间的相互依赖关系 ,这个文件在gradle 构建 flutter app / flutter module的时候会有用到,如果不熟悉建议看另一篇博文:深度了解Flutter APP的构建流程
注意:有人在新建了一个hello_flutter工程之后,pub get之后并没生成.flutter-plugins和.flutter-plugins-dependencies文件,那是因为这两个文件作用是gradle与pub之间的桥梁,如果插件/库里面没有包含有原生的相关的内容,是不会被加入到.flutter-plugins-dependencies和.flutter-plugins文件中的。
讲一个例子
好了讲到这里我们对flutter/dart是如何管理源码,版本,以及gradle是如何找到并且include flutter-plugin有了更深刻的认识,下面我们来简单介绍一下如何使用pub第三方库;
Pub官方库:https://pub.flutter-io.cn/
这里以官方date_format为例,介绍如何使用,首先使用pub库分为以下几个步骤:
  1. 在pub上找到date_format这个包(一般都有使用说明)
  2. 确定需要引入的版本,在pubspec.yaml中添加引入指定的date_format的版本
  3. IDE会检测到配置文件的改动,需要重新get dependencies,或者手动在pubspec.yaml同目录下执行flutter pub get命令下载第三方库
加入了date_format库之后的pubspec.yaml文件:
dependencies: flutter: sdk: flutter cupertino_icons: 1.0.2 date_format: 2.0.4

【Flutter学习|Flutter工程代码管理 pubspec.yaml、.packages 与 pubspec.lock文件的来龙去脉】date_format插件下载完后我们就可以在dart文件中使用该插件了。

    推荐阅读