fvm 实战:Windows 下 Flutter 多版本管理与升级回退
说实话我最早真没把 fvm 当回事。Flutter 装好PATH 配上全局往那一指哪个项目不是跑直到有一天我需要同时维护两个项目一个停在 Flutter 3.13团队要求锁版本不乱动另一个要试 Flutter 3.22 的新特性三天两头得跟上小版本。全局 SDK 换来换去光是来回改 PATH、重新跑 flutter doctor 就耗掉不少时间更别提一升级就把老项目的编译环境冲掉。fvmFlutter Version Management就是来解决这个问题的在 Windows 下它尤其好用因为它不像 macOS/Linux 那样有很多系统级 SDK 管理的天然优势反而更需要一个显式工具把多版本 Flutter 管起来。这篇文章不聊 fvm 的源码也不讲什么花活就讲 Windows 上从零装 fvm、日常怎么用、版本升级和回退怎么操作以及开发工具怎么对接。适合正在被多项目版本冲突折磨、或者准备升级 Flutter 但担心回不去的朋友参考。文中所有命令我都在 Windows 11 上实测过老系统 Windows 10 理论上也没区别照着抄就行。1. 为什么需要 fvm先看看全局 SDK 模式坑在哪1.1 全局 Flutter 的“版本锁死”问题默认的 Flutter 安装方式是把flutter/bin目录加进 PATH所有项目共用同一个 SDK。个人开发者写 demo 完全没问题但一旦你同时维护多个项目几个很现实的坑就会冒出来项目 A 依赖的老插件没跟上新版本编译直接挂项目 B 又必须用新版才能修某个 bug两边对 SDK 版本的要求是冲突的。执行flutter upgrade升级到新版本后想回退就只能删 SDK 目录或者重新下载解压还要改 PATH、重新跑 flutter doctor过程机械且容易出错。团队成员各自 Flutter 版本不一致有人 build 得过有人 build 不过最后定位半天发现只是 SDK 版本不一样。这里最痛的一点是Flutter 团队本身不推荐长期混用版本但在真实项目里你根本没法保证所有分支都立刻升级。flutter upgrade一执行整个项目可能就进入“半迁移”状态老语法报警告、依赖包要求更高 SDK、Gradle 配置不兼容。一旦出现这种情况你再想退回去成本往往比升级还高。1.2 fvm 是怎么把这件事解决的fvm 的思路不复杂它把不同版本的 Flutter SDK 下载到一个统一目录默认是FVM_HOME或者用户目录下的 fvm 缓存目录然后通过符号链接或路径切换的方式让每个项目在运行 flutter 命令时指向自己锁定的版本。提一个很多人拿 fvm 和 nvmNode 版本管理器类比的说法。nvm 切换的是当前 shell 的全局 node 版本fvm 更强的一点是支持项目级锁定。你在项目根目录执行fvm use 3.16.9它会生成版本配置文件之后在这个目录里用fvm flutter用的固定就是这个版本不会波及全局。团队成员 clone 仓库后只要执行fvm install或fvm use就能拉到同一个版本。这种“项目自描述”的思路其实比单纯切全局版本更符合工程化习惯。fvm 只管 Flutter 这一层它不会绕开 Android Studio、Xcode 等原生工具的限制。比如 Windows 桌面端编译需要 Visual Studio 的 C 工具链这是 VS 自己要去装的fvm 不背锅。但正因为职责单一它的核心命令不算多每个都很稳学起来成本很低。2. Windows 下安装 fvm三种方式与避坑要点2.1 方式一通过 Chocolatey 安装如果你机器上已经装了 Chocolatey安装 fvm 就一条命令choco install fvm -y要求是用管理员权限打开的 PowerShell 或 CMD。装完之后重新开一个终端敲fvm --version能出来版本号就算成功。这种方式最省心后续升级用choco upgrade fvm就行。我个人的建议是如果你本来就在用 choco 管理 Windows 软件优先走这条路。因为 Chocolatey 会处理好 PATH 和权限的细节不会出现“命令装好了却找不到”的尴尬。唯一要注意的是部分公司电脑的组策略会限制 choco报错信息五花八门遇到这种情况就换下面两种方式。2.2 方式二通过 pub global 激活fvm 本身是 Dart 写的所以也可以用 pub 全局激活的方式安装dart pub global activate fvm这里有个先决条件本机得有一个能用的 Dart 环境。如果你已经装过任意版本的 Flutter直接用 Flutter 自带的dart命令激活即可。激活成功后fvm 会被放到%LOCALAPPDATA%\Pub\Cache\bin目录下你需要确认这个目录在 PATH 里否则终端找不到fvm命令。提示用where fvm可以快速确认命令路径是否被系统识别。如果提示找不到打开“系统属性 - 环境变量”把%LOCALAPPDATA%\Pub\Cache\bin加到用户 PATH 中重新开终端即可。2.3 环境变量与安装后的自检不管用哪种方式装完我强烈建议把 fvm 的缓存目录挪出 C 盘。一个 Flutter 稳定版 SDK 解压后大概 2GB 以上多装几个版本 C 盘直接就爆了。我当时没注意默认缓存攒了六个版本后C 盘剩余空间一度只剩 3GB整个电脑都开始卡。推荐这样配环境变量FVM_HOMED:\fvm # fvm 的版本缓存目录 PUB_CACHED:\fvm\pub-cache # pub 包全局缓存避免重复下载依赖配置完记得把%FVM_HOME%\default\bin加到 PATH这个目录是 fvm 之后放置全局默认版本符号链接的地方不加进来的话fvm global切完版本你在其他目录敲flutter还是老版本。安装后的自检顺序fvm --version fvm help如果fvm help能列出 install、use、global、list 等子命令说明基础环境已经通了。接下来就可以开始装多版本 Flutter。3. 核心实操安装多版本、切换与升级回退3.1 先看有哪些版本fvm releases 命令fvm 安装前我习惯先看一眼远端有哪些可用版本fvm releases这个命令会列出 Flutter 官方发布过的稳定版、Beta 版、Dev 版等。如果你对某个大版本的小版本号没概念也可以用fvm releases stable只看稳定版列表。注意这个命令需要联网访问 Flutter 的 release 接口首次执行可能稍慢多等几秒就行不要急着 CtrlC。选版本有个小经验不要一上来就选最新稳定版多看两个指标——一是这个版本对应 Dart 版本是多少二是它发布的时间。如果项目里用的某个依赖包只支持到某个 Dart 版本那 Flutter 版本选太高反而会引入编译问题。3.2 安装指定版本并锁定项目fvm install 与 fvm use确认好版本号之后安装指定版本fvm install 3.16.9安装过程其实就是下载和解压对应版本的 Flutter SDK时间取决于网络。装完可以用fvm list确认本地已有哪些版本。接下来是最关键的一步在项目根目录执行fvm use 3.16.9执行后fvm 会在项目里做两件事生成版本配置文件新版本叫.fvmrc或fvm_config.json老版本就是.fvmrc记录当前项目锁定的版本号。创建.fvm目录里面有一个flutter_sdk符号链接指向真正的 SDK 缓存位置。以后在这个项目目录里凡是执行 Flutter 相关命令都要带 fvm 前缀fvm flutter --version fvm flutter pub get fvm flutter run -d windows等于说项目里的所有命令都被“绑”到了指定版本上。如果同一个仓库被不同同事 clone大家执行fvm use时看到的版本号是一致的就不会再出现“我这里能跑你那里跑不了”的情况。3.3 版本升级与回退的真实场景复现升级应该是最多人关心的。假设项目当前锁定在 Flutter 3.13.9你想试试 3.19.5传统做法是直接全局升级然后听天由命。用 fvm 可以这样做fvm install 3.19.5 fvm use 3.19.5 fvm flutter pub get fvm flutter run这几条命令执行完项目就已经在 3.19.5 上跑了。如果跑起来发现有问题比如某个第三方插件不兼容或者 Impeller 渲染引擎导致一些自定义画笔效果变了回退也非常直接# 回到项目根目录 fvm use 3.13.9 --force fvm flutter pub get fvm flutter run--force是干嘛的当项目里已经有一个锁定的版本而你要求切换时fvm 可能弹出确认提示加上--force就是跳过确认脚本化操作时更省心。这里额外提醒一个坑fvm 只管 SDK不管 pub 包的缓存。你从 3.19.5 回退到 3.13.9 后pubspec.lock可能已经被新版本的依赖解析逻辑改过了有些包的解析结果在旧 Dart SDK 下不兼容。这时候不要慌先git checkout pubspec.lock把它还原到项目锁定的版本然后重新fvm flutter pub get。如果项目里没提交 lock 文件也可以fvm flutter pub downgrade让 pub 自动解析出一套兼容旧版本的依赖组合。全局版本也可以用 fvm 管理。如果你希望平时在任意目录敲flutter都默认指向某个版本就执行fvm global 3.16.9这个命令会把符号链接写进%FVM_HOME%\default配合前面你配好的 PATH就能实现全局版本灵活切换。需要清理旧版本时fvm remove 3.13.9执行前看一眼fvm list确认这个版本没有被别的项目引用再删不迟。磁盘占用不是小事尤其你像我一样喜欢“先装再说”的定期清理是必须的。3.4 两个 Flutter 项目并行开发的实操建议多版本管理不只是命令的事日常习惯也很重要。我现在的标准做法就是每个项目目录内只用fvm flutter和fvm dart全局那个 flutter 命令几乎只在初始化新项目的时候用。这个习惯能避免很多“我明明 fvm use 了为什么还是老版本”的困惑。同时开两个项目调试时建议不同版本的进程分开跑尽量别共用同一个调试端口。Flutter 的调试服务默认端口是随机分配的正常不会冲突但如果你手动指定过--debug-port多个版本同时跑同一端口就会报地址占用。另外多版本环境下最怕的就是.dart_tool目录缓存错乱。切换 Flutter 版本之后建议老老实实执行一次fvm flutter clean fvm flutter pub get不要嫌慢这一步能把很多“玄学报错”扼杀在摇篮里。4. 开发工具配置与常见问题排查4.1 VS Code 接入 fvm别再手动改 SDK 路径VS Code 里如果直接在设置里指向某一个 Flutter SDK 路径那多版本切换就又回到手动模式了。更优雅的方式是在项目根目录的.vscode/settings.json里写{ dart.flutterSdkPath: ${workspaceFolder}/.fvm/flutter_sdk }这样打开项目时VS Code 会自动使用当前项目 fvm 锁定的 SDK 版本。注意这里用的是${workspaceFolder}变量不要写成绝对路径否则换个人 clone 就失效了。还有一种方式是 VS Code 的 Flutter 扩展本身会识别项目里的.fvm目录自动提示“是否使用当前项目的 Flutter SDK”我在新版扩展里遇到得比较多。但为了避免 IDE 抽风我仍然会在项目级 settings.json 里显式写好双保险。提示如果你用dart.flutterSdkPath之后VS Code 仍然提示找不到 Flutter SDK先到项目根目录执行一次fvm use 版本号确保.fvm/flutter_sdk符号链接真实存在。新 clone 下来的仓库往往还没执行这一步IDE 自然找不到。4.2 Android Studio 与命令行环境变量Android Studio 里的配置方式大同小异。打开 File - Settings - Languages Frameworks - Flutter把 Flutter SDK path 指向项目的.fvm/flutter_sdk。保存后重启一下 Android Studio让新的 SDK 路径生效。命令行层面的建议是PATH 里留一个 fvm 的全局面板就够了。你不需要把每个版本的 Flutter 路径都加进 PATH那样反而乱。日常在任意目录打开终端敲flutter --version看到的是fvm global指定的版本进入某个具体项目后一律用fvm flutter它读的是项目配置。这个组合最清晰也不容易出错。4.3 实战中常见的坑与排查方案这部分是我实操下来最想写的内容。fvm 本身不是万能的你在 Windows 上遇到的不少报错其实是被 fvm 切换版本后暴露出来的。报错一unable to find suitable Visual Studio toolchain这个报错一般出现在想编译 Windows 桌面端时。fvm 安装的 Flutter 只是 SDK不会替你装 Visual Studio。新版 Flutter 编译 Windows 目标要求系统里有 VS 的“使用 C 的桌面开发”工作负载或者至少装了 Visual Studio Build Tools。排查步骤打开 Visual Studio Installer确认安装了“使用 C 的桌面开发”工作负载。确认“Windows 10/11 SDK”组件存在有时工作负载装得不完整这个组件会被精简掉。装完之后重开终端运行flutter doctor -v看 Visual Studio 那一项是否显示已安装。如果只是想编译 Windows 桌面版装 Visual Studio Build Tools 也够用不需要完整版的 VS。但这个工具链和 fvm 没有关系属于 Windows 桌面开发的硬性前提容易在版本切换后第一次跑 Windows 目标时突然冒出来。报错二you are applying Flutters main Gradle plugin imperatively using the apply script method这个报错在 Flutter 版本升级后很常见尤其是老项目。新版 Flutter 推荐在 Gradle 里使用声明式插件 DSL老式项目里往往还是用apply plugin的方式引入 Flutter Gradle 插件。切换新版本后Flutter 的 Gradle 插件会直接拒绝老写法。我踩过之后总结的解法分两步如果只是想回退到旧版本继续干活直接fvm use 旧版本就能搞定报错一般随之消失。如果想留在新版本得动 Gradle 配置把 settings.gradle 里的pluginManagement和pluginsDSL 按官方迁移文档调整。这里其实体现出 fvm 的一个隐性价值它让你有足够的时间做渐进式迁移而不是被新版 SDK 赶着走。报错三fvm 命令找不到或者 fvm global 不生效多半是 PATH 没配全。用where fvm查看 fvm 所在路径用where flutter看全局 flutter 所在路径。如果flutter指向的还是老的 SDK 目录说明 PATH 里%FVM_HOME%\default\bin没有加进去或者加的顺序不对。报错四符号链接创建失败Windows 上执行fvm use时如果提示创建符号链接失败通常是权限问题。解决方式是启用“开发者模式”。位置在设置 - 隐私和安全性 - 开发者选项 - 开发人员模式打开后重启终端再试。如果不方便开开发者模式就用管理员权限执行终端。报错五C 盘空间被 fvm 和 pub 缓存占满前面提过这是我最痛的教训。解决方案就是把FVM_HOME和PUB_CACHE这两个环境变量都指到非系统盘并把旧的缓存目录手动清理掉。pub-cache 是个容易被忽略的大户flutter 项目跑多了这里轻松攒出几个 G 的依赖包。4.4 版本切换后的连带问题速查表问题可能原因快速处理flutter 命令版本没变化PATH 未指向 fvm default确认%FVM_HOME%\default\bin已加入 PATHVS Code 找不到 Flutter SDK项目没生成符号链接项目根目录执行fvm use 版本Windows 桌面编译失败缺少 VS C 工具链装 VS Build Tools 并确认 flutter doctorpub 依赖解析异常pubspec.lock 被新版本改过还原 lock 文件并重新 pub getC 盘空间不足SDK 和 pub 缓存在系统盘修改 FVM_HOME 和 PUB_CACHE 到其他盘Gradle 插件报错Flutter 版本升级引起不兼容回退版本或迁移到 plugins DSLfvm use 提示符号链接失败权限受限或开发者模式未开开启开发者模式或管理员终端执行5. 一点进阶玩法把 fvm 用出“云环境”的感觉fvm 用熟之后你会慢慢发现它不只是“切版本”的工具。因为版本配置文件是项目仓库的一部分它可以被 CI/CD 直接读取。比如公司内部构建机只要装了 fvm执行到项目目录时先fvm install再fvm flutter build构建环境就和本地完全一致了。这能省掉不少“本地能构建服务器构建失败”的扯皮。另外fvm 也是做 Flutter 版本适配测试的最好助手。比如你写了一个插件想知道它在 Flutter 3.13、3.16、3.19 下分别能不能编译不用一个个手动调整全局 SDK直接建三个目录分别锁不同版本跑一遍就知道了。我甚至见过有人用脚本循环fvm useflutter test来批量回归效率非常高。6. 总结我的使用心得最后分享一点我自己的习惯。一开始我总觉得 fvm 是给团队协作才用的个人开发者用不上试过之后才发现这个想法很片面。就算只有一个项目你也会有“想升级到新特性但怕踩坑”的时候。fvm 最打动我的地方是让升级这件事变成“可逆操作”先切新版本跑两轮自动化测试有问题一条命令退回旧版本心里稳得多。我现在的标准流程每个项目不管大小都在根目录维护一份 fvm 版本配置并纳入版本管理。同事新 clone 下来看一眼配置执行fvm install加fvm use就能复现环境。真别把小版本缓存全留着每个稳定版两个 G攒一年 C 盘直接爆定期用fvm remove清掉不再用的版本比清理什么 Windows 临时文件划算多了。工具这个事简单直接才撑得住长期用。fvm 在 Windows 上的价值就是让你在 Flutter 多版本这个混乱问题上找到一个足够简单、又足够可靠的支点。希望这篇实战记录能帮你少走一些弯路。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →