当前位置: 首页 > news >正文

Flutter 正在切换成 Monorepo 和支持 workspaces

其实关于 Monorepo 和 workspaces 相关内容在之前《Dart 3.5 发布,全新 Dart Roadmap Update》 和 《Flutter 之 ftcon24usa 大会,创始人分享 Flutter 十年发展史》 就有简单提到过,而目前来说刚好看到 flaux 这个新进展,所以就再展开来聊聊目前 Flutter 里进行中的 Monorepo 和 workspaces。

其实如果你不跑引擎,不提 PR 或者不看源码,那 monorepo 调整对你来说应该没什么正向影响。

monorepo

可能有人还没听说过 monorepo,先介绍下 monorepo(mono repository) ,它是一种项目代码的管理方式,就是将多个项目存储在一个 repo 中,在 monorepo 里多个项目的所有代码都存储在单个仓库里,这个集中式存储库包含 repo 中的所有组件、库和内部依赖项等。

monorepos 也不是什么新概念,很早之前 Google、Meta、Microsoft、 Twitter 等公司都在大规模使用 monorepos ,比如 ReactVscodeBabel 都使用了 monorepo,如下图所示可以看出来他们在形式和结果的区别:

更多可见原文:https://blog.bytebytego.com/p/ep62-why-does-google-use-monorepo

使用 monorepo 的最主要原因之一是简化代码管理,由于所有代码都存储在单个存储库中,因此可以更轻松地跟踪更改、保持版本一致性等,例如 Meta 的工程师曾就表示过:

Meta 的 monorepo 包含公司的大部分代码,可以轻松访问所有代码对开发人员的效率非常重要,工程师可以更深入地了解其依赖关系,调试整个堆栈中的问题,并实施功能或错误修复,所有这些都触手可及······

······版本控制是使用多个存储库时最复杂的问题之一,每个存储库都是独立的,团队可以自由决定要采用的依赖项版本,但是由于每个存储库都按照自己的节奏发展,这些不一致会导致项目可能包含同一依赖项的多个版本,从而导致后续版本控制的各种冲突·····

https://www.growingdev.net/p/what-it-is-like-to-work-in-metas

所以 monorepo 不仅仅只是将所有源代码“紧密放在一起”,更是确保存储库中各个库和应用相互兼容的重要工具:

简单点说人话就是:将现在 Flutter 项目下的 flutter/engineflutter/buildrootflutter/flutter 这三个存储库合并到单个 flutter/flutter 存储库中

采用 monorepo 对于目前 Flutter 来说有着许多好处,例如更方便的 CI 和更容易协作,同时提高代码共享的能力,例如在现在的 flutter/flutter 项目下,由于 flutter/flutter flutter/engine 是两个独立项目,所以经常可以看到一堆”无意义“的 Roll Engine PR 的记录存在:

“Roll Flutter Engine from····” 主要是为了更改 framework 引用的 engine 的版本,每次 engine 有新的提交的时候,都会在 framework 自动创建一个 PR,更新 engine ,当所有测试通过时,PR 就会自动合并。

而如果使用 monorepo , flutter/flutter flutter/engine 将不再是相互隔离的 repo ,在 CI 和版本管理上都会更轻便可控,例如一开始文章提到的 flutter/flaux ,就是目前 Flutter 正在测试合并流程的项目,在最终合并到主flutter/flutter 之前验证 monorepo 的仓库。

也就是 flutter/engine 这个 repo 最终会在未来的某个时间点被 Archive ,虽然这和 Flutter 以前解释说不适用 monorepo 的原因相违背, 但是这个阶段来看,Flutter 还是需要选择 monorepo。

对于 monorepo 而已,所有依赖都是一个来源,所以意味着不存在版本冲突和依赖地狱,同时 monorepo 还支持原子提交,在大规模重构里开发人员可以在一次提交中更新多个包或项目。

其实目前 pub 上很多项目都在使用类似 monorepo 的结构,例如 riverpod 、cfug/dio 、ubuntu/app-center 、Flame-Engine/Flame 等项目都在使用 melos 做 monorepos 管理,而 Flutter 这次也是通过自定义对应的 CI 基础能力来更新以支持合并后的 repo 构建,也就是 Flutter 针对 monorepo 结构自定义了一套新的 CI 系统,事实上 monorepo 核心之一,就是在于 CI 的搭建还有项目结构分层的处理上

更多可见:https://melos.invertase.dev/~melos-latest/#projects-using-melos 、https://github.com/orgs/flutter/projects/182/

总结

总结起来,Flutter 迁移到 monorepo 的好处在于:

  • 提交原子性:engine、framework 和 buildroot 的变更可以一起提交,更好管理

  • 减少依赖 :可以减少大量内部版本依赖和冲突问题,大规模减少类似 Roll 类型的历史提交等

  • 简化 PR:用户可以更直观和方便提交 PR,包括这个 PR 需要从 engine 到 framework 多方调整的时候

  • 更方便测试: engine 和 framework 可以在同套 CI 下测试调整

当然 monorepo 也带来了新的问题,例如一个 repo 下多个 Dart 项目的解析问题,这就不得不说下面的 workspaces 概念。

workspaces

在 Dart 3.5 的时候,Dart Roadmap 就提出了 pub workspaces 概念,核心就是在 monorepo 中实现多个相邻包的共享解析,比如「共享解析」可以解决类似编辑器中的 Analyzer 占用空间过大问题,因为它可以减少单独的上下文 context。

analysis_options.yaml 下的大量规则引入也会增加内存上涨,事实上 Dart Analyzer 的上下文数量一直是内存消耗大户。

在 dart#53874 提到过,由于 monorepo 结构化的原因,Analyzer 在工作的时候最终会为每个包及其所有依赖项加载了多个重复的 analysis contexts,从而导致 monorepo 里每个包 analysis 时在内存中生成了多个副本,最终出现内存占用过大问题:

而解决方案就是在这些 repo 中为每个依赖项创建一个共享解决方案,也就是这里提到的 pub workspaces ,通过 workspaces ,项目在 monorepo 中可以实现多个相邻包的共享解析,通过共享 Analyzer 等工具在分析每个包之间共享上下文,从而节省大量内存。

也就是 workspaces 可以让 monorepo 创建共享版本来优化依赖项解析速度和内存。

例如,你可以通过 workspace 关键字启用 workspaces 并引入对应的 packages 结构:

name: workspace
environment:sdk: ^3.5.0
workspace:- packages/package_a- packages/package_b

然后在 packages/package_a/pubspec.yamlpackages/package_b/pubspec.yaml 添加一行 resolution: workspace

name: package_a
environment:sdk: 3.5.0
resolution: workspacedependencies:# You can depend on packages inside the workspace:package_b: ^1.2.4 # This version constraint will be checked against the local version
dev_dependencies:test: ^1.0.0

此时你的项目就已经处于 workspace 的工作模式下,而 workspaces 主要是支持 workspaces 下 monorepo 的包之间的共享解析,例如在仓库中的任意位置运行 flutter pub get ,项目会将产生一个共享解析,具体表现为:只会在 root pubspec.yaml 同级目录生成 一个 root pubspec.lock

另外,通过 dart pub deps 也可以更清晰看到整个 workspace 的依赖关系,也可以更好管理和同步依赖,结合 monorepo 结构或者 melos 等工具的能力,会让整个项目更直观可控:

最后

可以看到 monorepo 和 workspaces 属于相辅相成的存在,而 monorepo 也不是单纯就是把东西放到一个 repo ,更多涉及项目结构的分层,包的细化还有最关键的 CI 工具支持等,同时 monorepo 也可以更好管理所有项目的依赖关系,甚至支持增量构建等等。

总的来说 monorepo 并不是什么新鲜东西,只是到了这个阶段 Flutter 所需要做的一个调整,之前采用 multi repo 是规划里把多个 repo 当作独立产品,而现在是作为一个整体项目来管理的情况下,自然选择 monorepo 更合适。

参考资料

  • https://github.com/dart-lang/sdk/issues/53875

  • https://github.com/dart-lang/pub-dev/pull/7762

  • https://github.com/dart-lang/pub/issues/4391

  • https://github.com/dart-lang/pub/issues/4127

  • https://docs.google.com/document/d/1UEEAGdWIgVf0X7o8WPQCPmL4LSzaGCfJTM0pURoDLfE/edit?resourcekey=0-c5CMaOoc_pg3ZwJKMAM0og&tab=t.0

  • https://github.com/flutter/engine/blob/main/pubspec.yaml

  • https://github.com/orgs/flutter/projects/182

  • https://github.com/flutter/flaux

  • https://github.com/flutter/cocoon

相关文章:

Flutter 正在切换成 Monorepo 和支持 workspaces

其实关于 Monorepo 和 workspaces 相关内容在之前《Dart 3.5 发布,全新 Dart Roadmap Update》 和 《Flutter 之 ftcon24usa 大会,创始人分享 Flutter 十年发展史》 就有简单提到过,而目前来说刚好看到 flaux 这个新进展,所以就再…...

小白初入Android_studio所遇到的坑以及怎么解决

1. 安装Android_studio 参考:Android Studio 安装配置教程 - Windows(详细版)-CSDN博客 Android Studio超级详细讲解下载、安装配置教程(建议收藏)_androidstudio-CSDN博客 想下旧版本的android_studio的地址(仅供参考&#xf…...

NetCore使用Aop和内存缓存对接口、方法进行数据缓存

通过Aop内存缓存对接口、方法进行缓存 源码地址https://gitee.com/wangbenchi66/nuget 1. nuget包引入 必须引入包 至少在2024.11.7以上 <PackageReference Include"WBC66.Cache.Core" Version"2024.11.7" />必须开启内存缓存 否则后续步骤无法正…...

playwright学习记录2--定位方式

快捷导航 定位方式&#xff1a;元素操作断言方式自动等待 定位方式&#xff1a; csspage.get_by_role() 通过显式和隐式可访问性属性进行定位。page.get_by_text() 按文本内容定位。page.get_by_label() 通过关联标签的文本定位表单控件。page.get_by_placeholder() 通过占位符…...

响应式网页设计--html

一&#xff0c;HTML 文档的基本结构 一个典型的 HTML 文档包含了几个主要部分&#xff0c;基本结构如下(本文以下出现的所有代码都可以套入下面示例进行测试)&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8&q…...

C#核心(8) 静态成员

前言 先前我们已经学习了成员变量以及成员属性。 静态成员对于在整个应用程序中共享数据和功能非常有用。它们可以用于跟踪全局状态、共享常量和实现单例模式等。但是需要注意的是&#xff0c;过度使用静态成员可能导致代码变得难以维护和测试&#xff0c;因此应谨慎使用。其…...

关于git使用的图文教程(包括基本使用,处理冲突问题等等)超详细

目录 用户签名,初始化git git提交流程图 提交到本地库 版本穿梭 分支操作 分支合并冲突 团队协作 github的使用 推送代码 克隆 拉取代码 团队协作冲突 团队协作之分支管理 推送分支到分支&#xff1a; 拉去远程库分支到本地库&#xff1a; 本地删除远程分支&am…...

Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析

在前端开发的广阔天地中&#xff0c;Axios 犹如一颗璀璨的明星&#xff0c;为我们与服务器之间的通信搭建起坚实的桥梁。其中&#xff0c;responseType 属性更是赋予了我们灵活处理服务器响应的强大能力。 一、Axios 的 responseType 属性值及示例 1.arraybuffer 当我们将 r…...

redis集群介绍

1. 节点&#xff08;Node&#xff09;&#xff1a; • Redis集群中的单个Redis服务器实例。每个节点都运行一个Redis服务器进程&#xff0c;并维护自己的数据。 2. 分片&#xff08;Sharding&#xff09;&#xff1a; • 将数据集分割成多个部分&#xff0c;并分布到不同的节点…...

JDK中常用的包有哪些?

1.java.lang 描述&#xff1a;包含Java语言的核心类&#xff0c;不需要显式导入。 常用类&#xff1a;Object、String、Math、System、Thread、Exception等。 2.java.util 描述&#xff1a;提供了集合框架、日期和时间功能、随机数生成、扫描和格式化等实用工具类。 常用类…...

校园官网练习---web

HTML&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>西安工商学院</title><…...

MySQL中指定字段的某个值排在前面

一 需求 如果我们想讲表中指定的字段的某一个值排序在最前面应该如何处理&#xff1f; 二 实现方式 方法 1、使用<>&#xff0c;xml中使用<![CDATA[跳过解析的特殊符号]]>或者<&#xff08;小于符号&#xff09;>&#xff08;大于符号&#xff09; ORDER …...

【51单片机】I2C总线详解 + AT24C02

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 AT24C02介绍存储器 I2C总线介绍I2C时序结构数据帧AT24C02数据帧 编程实例 —— 按键控制数据大小&存储器写入读出 AT24C02介绍 …...

直接插入排序法

任务描述 本关任务&#xff1a;要求编写程序实现直接插入排序的功能。 相关知识 直接插入排序&#xff0c;是指将无序序列中的各元素依次插入到已经有序的数组中。 假设数组中前 i-1 元素已经有序&#xff0c;现在要将线性表中第 i 个元素插入到前面的有序子表中&#xff0c;…...

mysql中InnoDB索引与MyISAM索引

mysql索引 InnoDB 索引存储 主键索引&#xff08;聚簇索引&#xff09; 定义&#xff1a;主键索引是 InnoDB 存储引擎的聚簇索引&#xff0c;它决定了表中数据的物理存储顺序。每个 InnoDB 表都有一个且仅有一个聚簇索引。存储&#xff1a;主键索引的叶子节点直接包含表的数…...

Redis如何保证数据不丢失(可靠性)

本文主要以学习为主&#xff0c;详细参考&#xff1a;微信公众平台 Redis 保证数据不丢失的主要手段有两个&#xff1a; 持久化 多机部署 我们分别来看它们两的具体实现细节。 1.Redis 持久化 持久化是指将数据从内存中存储到持久化存储介质中&#xff08;如硬盘&#xf…...

【计网】物理层学习笔记

【计网】物理层 物理层概述 物理层要实现的功能 在各种传输媒体上传输比特0和1&#xff0c;进而为上面的数据链路层提供透明传输比特流的作用。 物理层接口特性 物理层之下的传输媒体 传输媒体是计网设备之间的物理通路&#xff0c;也称为传输介质。 传输媒体并不包含在…...

vue链接跳转

在 Vue 3 的组合式 API 中&#xff0c;你可以使用 ref 和 setup 函数来实现外部链接跳转功能。 方法 1&#xff1a;使用 click 和 window.open&#xff08;新标签页跳转&#xff09; 这种方式在点击时会打开一个新标签页并跳转到外部链接。 <menu-item value"item2&…...

IP地址是电脑自带的吗?是根据什么而决定的‌

IP地址并非电脑自带&#xff0c;而是由网络运营商或网络服务提供商通过特定的协议和机制进行分配和管理的。要深入理解IP地址的来源和决定因素&#xff0c;我们需要从IP地址的基本概念、分配方式以及影响分配的因素等多个方面进行探讨。 IP地址&#xff0c;即互联网协议地址&am…...

JavaFX史上最全教程 - Shape - JavaFX矩形椭圆

avaFX Shape类定义了常见的形状&#xff0c;如线&#xff0c;矩形&#xff0c;圆&#xff0c;Arc&#xff0c;CubicCurve&#xff0c;Ellipse和QuadCurve。 在场景图上绘制矩形需要宽度&#xff0c;高度和左上角的&#xff08;x&#xff0c;y&#xff09;位置。 要在JavaFX中…...

SpringBoot实现的企业资产管理系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…...

python-读写Excel:openpyxl-(4)下拉选项设置

使用openpyxl库的DataValidation对象方法可添加下拉选择列表。 DataValidation参数说明&#xff1a; type&#xff1a; 数据类型("whole", "decimal", "list", "date", "time", "textLength", "custom"…...

【C++】详解RAII思想与智能指针

&#x1f308; 个人主页&#xff1a;谁在夜里看海. &#x1f525; 个人专栏&#xff1a;《C系列》《Linux系列》 ⛰️ 丢掉幻想&#xff0c;准备斗争 目录 引言 内存泄漏 内存泄漏的危害 内存泄漏的处理 一、RAII思想 二、智能指针 1.auto_ptr 实现原理 模拟实现 弊端…...

Qt 环境实现视频和音频播放

在这个示例中&#xff0c;我们将使用 FFmpeg 进行视频和音频的解码&#xff0c;并使用 Qt 的界面进行显示和控制。为了实现音频和视频的解码以及同步显示&#xff0c;我们需要使用 FFmpeg 的解码库进行视频和音频解码&#xff0c;使用 Qt 的 QLabel 显示解码后的视频帧&#xf…...

【人工智能训练师】7 大数据处理与应用

大数据处理与应用&#xff08;Hive技术&#xff09;(0/100分) 1.本地开发工具连接Hadoop集群 1.本次环境版本为Hadoop2.7.7&#xff0c;对应eclips插件存放于云主机master:/usr/package277/中。 2.本机映射名为hadoop000&#xff0c;云主机Hadoop/Hive的hosts文件中IP需要修改…...

nginx配置文件介绍及示例

一、nginx配置文件一共有main&#xff0c;http&#xff0c;server&#xff0c;location&#xff0c;upstream&#xff0c;stream&#xff0c;events7个块。 step 1: main 块 作用&#xff1a;main 块是 Nginx 配置文件的顶级块&#xff0c;用于设置一些全局的参数和配置&…...

如何在算家云搭建YOLOv5(物体检测)

一、YOLOv5简介 YOLOv5 模型是一种以实时物体检测闻名的计算机视觉模型&#xff0c;由 Ultralytics 开发&#xff0c;并于 2020 年年中发布。它是 YOLO 系列的升级版&#xff0c;继承了 YOLO 系列以实时物体检测能力而著称的特点。 二、模型搭建流程 1.选择模型实例 在应用…...

现场工程师日记-MSYS2迅速部署PostgreSQL主从备份数据库

文章目录 一、概要二、整体架构流程1. 安装 MSYS2 环境2. 安装postgresql 三、技术名词解释1.MSYS22.postgresql 四、技术细节1. 创建主数据库2.添加从数据库复制权限3. 按需修改参数&#xff08;1&#xff09;WAL保留空间&#xff08;2&#xff09;监听地址 4. 启动主服务器5.…...

使用Element UI实现一个拖拽图片上传,并可以Ctrl + V获取图片实现文件上传

要在 Element UI 的拖拽上传组件中实现 Ctrl V 图片上传功能&#xff0c;可以通过监听键盘事件来捕获粘贴操作&#xff0c;并将粘贴的图片数据上传到服务器。 版本V1&#xff0c;实现获取粘贴板中的文件 注意&#xff0c;本案例需要再你已经安装了Element UI并在项目中正确配…...

私域流量圈层在新消费时代的机遇与挑战:兼论开源 AI 智能名片、2 + 1 链动模式、S2B2C 商城小程序的应用

摘要&#xff1a;本文剖析了私域流量圈层在新消费时代呈现出的独特温度与信任优势&#xff0c;阐述了从传统销售到新消费转型中用户心理的变化。同时&#xff0c;强调了内容对于私域流量的关键作用&#xff0c;并分析开源 AI 智能名片、2 1 链动模式、S2B2C 商城小程序在私域流…...

甘肃手机版建站系统信息/文案发布平台

1、这个小游戏对于初学者而言&#xff0c;就是为了让大家练习方法的定义&#xff0c;参数的设定和使用。同时在开始需求分析中得知&#xff0c;如果我们发现一些代码重复出现&#xff0c;我们就要开始想&#xff0c;要不要写个方法来解决。比如地图的绘制&#xff0c;地图的绘制…...

长安公司网站建设/2024年阳性最新症状

存储过程 在我们编写程序中&#xff0c;往往需要一些存储过程&#xff0c;在LINQ to SQL中怎么使用呢&#xff1f;也许比原来的更简单些。下面我们以NORTHWND.MDF数据库中自带的几个存储过程来理解一下。 1.标量返回 在数据库中&#xff0c;有名为Customers Count By Region的…...

网站开发dede/域名注册需要什么条件

所有软件系统中都必须包含一项关键组件&#xff0c;那就是用于存储、检索和分析数据的数据库。本文中&#xff0c;我们将和大家一起探讨适用于算法交易平台的数据库都会有哪些特性&#xff1f;有哪些可选择的数据库&#xff1f; 从广义层面来看&#xff0c;数据库提供了记录和…...

wordpress 字母标签页/百度网盘客服电话24小时

Vue项目的搭建流程 1、检查是否安装node node -v2、检查是否安装vue vue -V3、下载vue-cli框架 在这里我用的是命令窗口下载&#xff0c;还可以用可视化窗口下载 vue create demo //回车在这里选择最后一个&#xff0c;手动选择功能&#xff0c;然后回车 在这里可以选择…...

乌鲁木齐哪里有做网站的公司/推广策略都有哪些

项目开源地址 https://gitee.com/splot/php-screw-plushttps://github.com/del-xiong/screw-plus 虽然作者已经停止更新&#xff0c;但还是可以用的&#xff0c;相比sg11而言&#xff0c;这个是完全免费的&#xff0c;一般小白是破解不了的&#xff0c;反正我不懂怎么破解。 加…...

wordpress 跳转 微信/广州网站定制多少钱

记得老早以前就看到有人把反射称之为“性能杀手",正好目前正在做的erp系统为了实现扩展&#xff0c;系统就是架构在反射的基础之上&#xff0c;数据交互也都是通过反射来实现。首先系统会产生太多dll,现在刚刚起步&#xff0c;已经高达43个之多&#xff0c;由于erp系统具有…...