ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

fvm多版本管理实战:Windows环境Flutter SDK切换与项目版本锁定指南

fvm多版本管理实战:Windows环境Flutter SDK切换与项目版本锁定指南 1. 为什么要用fvm管理Flutter版本本地多项目共存的现实问题如果你同时维护几个Flutter项目肯定遇到过这样的尴尬项目A用的是Flutter 3.16项目B因为历史依赖锁在了Flutter 3.7项目C可能已经追新到了3.22。在没有fvm之前常规做法就是不断卸载重装Flutter SDK或者手动修改PATH环境变量指向不同版本的SDK目录。这套操作有多烦经历过的人应该都有体会。1.1 版本切换的原始痛点先说说我自己踩过的坑。之前接了一个维护老项目的工作项目依赖的某个插件包在Flutter 3.19之后就不再维护了新版本API变动导致编译直接报错。当时我用的Flutter版本是3.24为了跑这个项目只能忍痛降级。降级过程中先卸载旧版、删除缓存、重新下载3.7的SDK压缩包再配置环境变量前后折腾了两个多小时。等项目跑通之后我自己的主项目又需要回到3.24又重复了一遍卸载安装的流程。这还只是麻烦层面的问题更头疼的是缓存共用。Flutter的pub缓存默认是全局的不同版本的Flutter共享同一个pub cache路径版本跨度大了之后经常出现某个包在3.7下编译正常、在3.24下却因为SDK版本约束直接被拒绝解析导致两个项目的依赖互相污染。你刚把主项目跑起来切回老项目就得重新pub get而且很可能解析出一堆版本冲突。1.2 fvm解决的核心问题fvmFlutter Version Management的思路和nvm管理Node.js版本几乎一模一样核心就三件事一是把多个Flutter SDK版本集中存放在一个统一目录下互不干扰二是在项目级别记录当前项目使用的Flutter版本三是通过软链接或者环境变量切换实现一条命令快速换版本。fvm的全称是Flutter Version Management官方地址在fvm.appGitHub仓库是leoafarias/fvm。它最实用的特性有三个项目级版本锁定在项目根目录执行fvm use 3.19.6之后会生成一个.fvmrc文件里面记录了当前项目需要的Flutter版本。后续任何人在这个项目里执行fvm install或者fvm usefvm会自动读取配置并切换到对应版本团队协作时消除了我本地能跑你本地报错的环境差异问题。全局默认版本管理fvm global 3.24.0可以设置系统默认的Flutter版本新项目默认使用这个版本不用每创建一个项目都手动切换。SDK隔离存储所有通过fvm安装的Flutter SDK都放在同一个根目录下Windows默认是%USERPROFILE%\fvm\versions每个版本独立存在互不干扰。pub cache也做了版本隔离不会出现依赖缓存串版本的问题。2. Windows环境下fvm安装与初始化的完整过程fvm的安装方式在不同平台上有区别Windows下我推荐用包管理器安装最简单省事。2.1 通过Chocolatey安装fvm如果你机器上已经装了Chocolatey直接执行choco install fvm装完之后重新打开一个PowerShell窗口执行fvm --version确认安装成功。如果输出类似fvm 3.1.7的版本号说明安装这一关过了。没有Chocolatey的话也可以用GitHub Release里提供的Windows安装包下载最新版本的fvm-windows.zip解压之后把可执行文件所在目录手动添加到系统PATH里。考虑到后续fvm还会自动维护一些内部命令这个方式相对麻烦建议还是先装Chocolatey一次性解决。提示确认安装成功后先执行一次fvm doctor检查环境完整性。它会自动检测Git、Visual Studio构建工具、Android Studio这些Flutter开发的基础依赖是否就位有问题会直接提示。2.2 指定fvm的SDK存储目录fvm默认会把所有版本的Flutter SDK存放在%USERPROFILE%\fvm\versions路径下。如果你有特殊需求比如C盘空间紧张想放到其他盘可以通过环境变量FVM_HOME来指定存储位置。我的做法是把fvm的SDK放到D盘开发目录下这样即使系统重装SDK还在省去重新下载的时间# 先创建目录 mkdir D:\dev\fvm # 设置用户级环境变量 setx FVM_HOME D:\dev\fvm设置完环境变量后需要重新打开终端窗口才能生效然后执行fvm doctor验证一下是否读取到了新路径。2.3 安装第一个Flutter版本fvm本身只是管理工具不附带任何Flutter SDK。需要先安装一个版本才能开始工作# 安装稳定版最新版本 fvm install stable # 或者指定具体版本号 fvm install 3.22.3 fvm install 3.19.6fvm支持直接在命令中指定stable、beta这样的大版本通道更推荐直接指定版本号这样版本可追溯性更强。项目要求什么版本就安装什么版本全部需求列成清单之后一条一条执行即可。安装过程中fvm会从Flutter官方仓库下载对应版本的SDK压缩包并自动解压耗时取决于网络状况一般3.22这种体积的包大概需要5到10分钟。安装完成之后执行fvm list就能看到当前机器上所有已安装的Flutter版本列表。我本机现在就装了好几个版本从3.7.12到3.24.5都有各项目按需切换。3. fvm的核心工作流项目级版本锁定与全局版本切换fvm日常使用频率最高的就是fvm use和fvm global这两条命令。前者管项目后者管全局理解清楚这两个概念就不会用糊涂。3.1 项目级版本绑定在任何一个Flutter项目根目录下执行fvm use 3.19.6fvm会做两件事第一检查本机是否已经安装了3.19.6如果没有会自动提示并安装第二在当前项目目录下生成一个.fvmrc文件内容长这样{ flutter: 3.19.6 }这个文件就是项目版本锁定的依据建议提交到git仓库。团队其他成员拉取代码后在项目里执行fvm use就会自动读取.fvmrc并切换到对应版本不需要再去问你们用的哪个版本。另外执行fvm use时fvm还会在项目根目录生成一个.fvm文件夹里面是一个指向真实SDK路径的软链接。这个文件夹一般不需要提交到git仓库在.gitignore里加上.fvm/即可。执行完fvm use之后有个容易忽略的问题在当前终端窗口里Flutter命令并不会自动切换成fvm管理的版本。你还需要用fvm flutter来调用项目绑定的Flutter版本或者用下面的方式重新打开终端让软链接生效。3.2 fvm flutter与fvm dart的使用在项目目录下所有原本执行flutter命令的地方都要改成fvm flutterfvm flutter pub get fvm flutter run fvm flutter build apkfvm会自动读取当前项目.fvmrc中指定的版本去执行这些命令不会用错。同样的dart命令对应的是fvm dart。这个习惯刚开始确实不太容易适应尤其是直接在项目根目录敲flutter run的时候正确做法是敲fvm flutter run。不过适应期很短因为fvm会在非项目目录执行时给出友好的提示信息提醒你这是一个fvm管理的项目。3.3 设置全局默认版本不是所有场景都跟具体项目绑定。比如你新建一个测试项目压根还没有执行fvm use此时fvm默认调用的是全局版本。全局版本用这个命令设置fvm global 3.24.0设置全局版本之后fvm会在系统PATH中加入一个指向当前全局版本SDK的链接让flutter命令可以直接使用日常新建项目直接就能跑。注意fvm global切换的版本只在重新打开的终端窗口中生效因为PATH环境变量在会话启动时就已经定下来了。另外全局版本主要用于临时测试和新建项目正经的正式项目还是建议在项目根目录执行fvm use把版本固化下来。全局版本的版本号修改后所有未绑定版本的终端都会受影响容易造成刚才还能跑现在突然不行了的假象。4. Flutter版本升级与回退的实战操作fvm的核心价值在版本升级和回退时体现得最明显。以前我升级Flutter版本最大的顾虑就是升级后发现项目编译不通过想回退又要重新折腾一遍环境。有了fvm之后升级再也不用破釜沉舟了。4.1 升级到新版本升级一个已有项目的Flutter版本操作流程是这样的# 1. 安装新版本 fvm install 3.27.0 # 2. 项目切换 fvm use 3.27.0 # 3. 重新拉取依赖 fvm flutter pub get # 4. 跑一下测试和构建验证 fvm flutter analyze fvm flutter test fvm flutter build apk --debug如果测试和构建都通过了升级完成。如果报错说明项目里有API变化或者依赖兼容性问题此时只需要在你的项目代码里逐一修复即可再也不用手忙脚乱地去卸载重装SDK了。这里有个细节想分享下我的经验每次升级的跨度不宜过大从一个版本跳到隔了很多个版本的大跨度升级容易积累太多兼容性问题排查起来麻烦。我一般是隔两三个小版本升一次比如3.24升3.27而不是从3.19直接跳到3.29。4.2 回退到旧版本回退比升级还简单因为旧版本还在fvm的仓库里存着# 查看本机已安装的可用版本 fvm list # 项目重新绑定旧版本 fvm use 3.19.6 # 重新拉取依赖 fvm flutter pub get这个过程不需要删除、不需要重新下载切换和依赖拉取加起来不超过两分钟。我实际用下来回退之后唯一需要留意的是Android的Gradle缓存在版本切换后偶尔会重建一次首次编译会稍慢多等一会儿就能看到正常的构建输出。4.3 安装并切换一个全新的试验版本如果你只是想体验一下新版本Flutter的特性又不想影响当前正在进行的项目可以先把新版本装进fvm然后单独建一个目录跑一下demo验证效果验证完直接删掉这个目录就可以了当前项目完全不受影响。fvm隔离存储的机制让这种平行试验变得特别轻松。5. IDE与工具链的版本联动配置命令行切好版本只是第一步IDE里如果用错版本照样寸步难行。VS Code和Android Studio各自都要做对应的联动设置。5.1 VS Code的配置VS Code打开Flutter项目后默认使用flutter全局命令对应的SDK。要让它使用fvm管理的项目特定版本在项目根目录的.vscode/settings.json里加上一行{ dart.flutterSdkPath: .fvm/flutter_sdk }这里的关键是路径得指向项目根目录下的.fvm软链接。fvm在fvm use阶段已经帮我们建好了链接关系所以这里直接用相对路径就行。设置完之后重启VS Code状态栏右下角的Flutter版本应该显示为当前项目绑定版本。我在多版本切换测试时发现如果VS Code不重启有些版本相关的提示比如LSP的SDK版本信息不会立即刷新重启一下最稳妥。5.2 Android Studio的配置Android Studio的配置稍微绕一点。打开File - Settings - Languages Frameworks - Flutter把Flutter SDK path改成fvm的SDK实际路径。注意这里不能用项目根目录的相对路径需要指向真实的SDK存储路径因为Android Studio的配置是全局的不像VS Code按项目读取。如果你用fvm global 3.24.0设置了全局版本可以把Android Studio的Flutter SDK路径指到对应版本的实际路径比如D:\dev\fvm\versions\3.24.0。但如果经常在多个项目间切换这种方式就不靠谱了因为全局版本一变Android Studio里配置的路径就失效需要频繁去改设置项。我的做法是Android Studio的Flutter SDK路径保持指向一个固定的全局稳定版本日常在这个IDE里只做该版本兼容范围内的开发。需要用其他版本做验证时切回VS Code操作两个IDE各司其职。提示VS Code的.fvm/flutterSdkPath配置在fvm 2.x之后的版本推荐直接写成.fvm/flutter_sdk旧的写法可能不兼容新版fvm遇到配置不生效可以检查下这个字段的写法。5.3 终端环境的PATH联动fvm global切换版本之后当前已打开的终端窗口中的flutter命令不会立即切换因为PATH变量在窗口开启时就已经确定了。我看到不少人在这一步以为fvm坏了其实只需要关掉终端重开一个新的即可。另外fvm会在%USERPROFILE%\fvm\default路径下维护一个指向当前全局版本SDK的软链接。即使你不清楚fvm内部逻辑只要确保这个软链接存在且指向正确版本flutter命令就能正常工作。6. Windows下使用fvm的坑版本缓存、镜像源与Gradle冲突fvm在Windows上整体很稳定但使用时间长了你总会碰到几个奇怪的小问题这里把我踩过的坑集中说一下。6.1 国内网络下载Flutter SDK慢或失败fvm安装版本时是从Flutter官方存储下载SDK国内网络环境下载大文件经常超时。这种问题不需要折腾fvm本身设置一下镜像环境变量即可让fvm自动走国内镜像# 设置Flutter镜像源 setx FLUTTER_STORAGE_BASE_URL https://storage.flutter-io.cn setx PUB_HOSTED_URL https://pub.flutter-io.cn设置完镜像后重新打开终端再执行fvm install 3.19.6速度会有肉眼可见的提升。需要注意的是这两个变量最好在安装Flutter SDK之前设置因为首次安装时fvm需要下载SDK和Dart SDK依赖这两个下载源是对应的。如果已经装完再设变量对已装好的版本没有影响只对后续新版本有效。6.2 fvm缓存目录占用过多磁盘空间fvm把每个版本的Flutter SDK完整存放在独立目录下版本装多了磁盘占用相当可观。我自己观察过每个版本的SDK加Dart SDK大约占用2.5GB到3.5GB不等装8个版本就是差不多30GB。清理不需要的版本直接这样操作fvm remove 3.7.12它会删除对应的SDK目录并清理引用记录。我建议定期用fvm list看一下本机装了哪些版本只保留最近一两个稳定版和项目实际在用的版本。不过注意执行fvm remove之前确认一下没有项目还在引用这个版本否则下次fvm use不得不再重新装一遍。6.3 Gradle构建缓存与Flutter版本的耦合问题所有Flutter项目在构建Android端时都会依赖本地的Gradle缓存而不同Flutter版本默认生成的Gradle版本不一样。切换版本后第一次构建可能会自动下载对应版本的Gradle wrapper这又是个不小的下载量。我的建议是在项目正式升级Flutter版本之后执行一次flutter clean清除旧的构建产物然后重新fvm flutter pub get和构建。虽然首次构建时间会变长但能避免很多来源不明的奇怪报错。7. 团队协作场景下fvm的最佳实践配置fvm不只是个人开发利器在团队协作中价值更大。我团队现在就全员使用fvm统一了项目版本管理流程基本消除了我本地能编译你那边报错这种问题。7.1 用.fvmrc文件统一团队版本所有项目根目录都提交.fvmrc文件里面写清楚该项目使用的Flutter版本。新人加入时按照项目README指引执行两条命令就行fvm install fvm usefvm install不带参数时会自动读取当前项目.fvmrc中声明的版本并安装fvm use会自动切换。全流程不需要知道具体版本号是多少。7.2 CI/CD流水线中的fvm集成我们的CI流水线GitHub Actions和Jenkins都有在构建步骤里增加了fvm环境准备steps: - uses: actions/checkoutv4 - name: Setup fvm run: | dart pub global activate fvm fvm install fvm use - name: Build run: | fvm flutter pub get fvm flutter build apk --release这样CI环境和本地环境用的是完全相同的Flutter版本不再出现本地构建正常但CI挂了这类问题。7.3 版本升级的团队协作流程我们团队升级Flutter版本不是某个人自己升级完就完事而是有个不太严格的流程先在个人分支上执行fvm use 新版本号跑一遍完整的analyze、test、build解决掉当前代码的所有兼容问题提交一个只更新.fvmrc和修复兼容性代码的PR团队其他成员拉取代码后执行fvm use自动切到新版本然后跑各自的模块整个过程前后不超过十分钟没有一个人需要手动去装SDK或者改PATH。对比一下以前没有fvm的时候一次版本升级经常要折腾整个组一两天效率提升非常明显。8. 我常用的fvm高频命令速查表用熟之后你会发现真正高频的命令也就十条以内整理成速查表方便查命令功能使用频率fvm install 版本号安装指定版本Flutter SDK中fvm use 版本号绑定项目版本高fvm global 版本号设置全局默认版本中fvm list查看本机已安装版本高fvm remove 版本号删除某个版本低fvm flutter 命令用项目版本执行Flutter命令极高fvm dart 命令用项目版本执行Dart命令中fvm doctor环境自检低fvm --version查看fvm自身版本低关于fvm自身的升级直接fvm工具本身走包管理器更新简单方便。fvm升级不影响已安装的Flutter版本这点不用担心。最后分享一个实际使用中的个人习惯每创建一个新项目第一件事就是fvm use绑定版本而不是等跑起来再处理。用fvm之后项目里的README还会附上一行fvm install fvm use作为环境准备命令。新环境准备时间从以前的一两个小时缩短到十几分钟回想当年手动下载SDK、解压、配置PATH的折腾过程现在是真的回不去了。
返回列表