fvm 实战:Windows 下 Flutter 多版本管理与升级回退
2026/9/17 7:08:55 网站建设 项目流程

说实话,我最早真没把 fvm 当回事。Flutter 装好,PATH 配上,全局往那一指,哪个项目不是跑?直到有一天我需要同时维护两个项目:一个停在 Flutter 3.13,团队要求锁版本不乱动;另一个要试 Flutter 3.22 的新特性,三天两头得跟上小版本。全局 SDK 换来换去,光是来回改 PATH、重新跑 flutter doctor 就耗掉不少时间,更别提一升级就把老项目的编译环境冲掉。fvm(Flutter 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 和 nvm(Node 版本管理器)类比的说法。nvm 切换的是当前 shell 的全局 node 版本,fvm 更强的一点是支持项目级锁定。你在项目根目录执行fvm use 3.16.9,它会生成版本配置文件,之后在这个目录里用fvm flutter,用的固定就是这个版本,不会波及全局。团队成员 clone 仓库后只要执行fvm installfvm 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_HOME=D:\fvm # fvm 的版本缓存目录 PUB_CACHE=D:\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 接口,首次执行可能稍慢,多等几秒就行,不要急着 Ctrl+C。

选版本有个小经验:不要一上来就选最新稳定版,多看两个指标——一是这个版本对应 Dart 版本是多少,二是它发布的时间。如果项目里用的某个依赖包只支持到某个 Dart 版本,那 Flutter 版本选太高反而会引入编译问题。

3.2 安装指定版本并锁定项目:fvm install 与 fvm use

确认好版本号之后,安装指定版本:

fvm install 3.16.9

安装过程其实就是下载和解压对应版本的 Flutter SDK,时间取决于网络。装完可以用fvm list确认本地已有哪些版本。

接下来是最关键的一步:在项目根目录执行:

fvm use 3.16.9

执行后,fvm 会在项目里做两件事:

  1. 生成版本配置文件,新版本叫.fvmrcfvm_config.json,老版本就是.fvmrc,记录当前项目锁定的版本号。
  2. 创建.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 flutterfvm 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。

排查步骤:

  1. 打开 Visual Studio Installer,确认安装了“使用 C++ 的桌面开发”工作负载。
  2. 确认“Windows 10/11 SDK”组件存在,有时工作负载装得不完整,这个组件会被精简掉。
  3. 装完之后重开终端,运行flutter doctor -v,看 Visual Studio 那一项是否显示已安装。

如果只是想编译 Windows 桌面版,装 Visual Studio Build Tools 也够用,不需要完整版的 VS。但这个工具链和 fvm 没有关系,属于 Windows 桌面开发的硬性前提,容易在版本切换后第一次跑 Windows 目标时突然冒出来。

报错二:you are applying Flutter's main Gradle plugin imperatively using the apply script method

这个报错在 Flutter 版本升级后很常见,尤其是老项目。新版 Flutter 推荐在 Gradle 里使用声明式插件 DSL,老式项目里往往还是用apply plugin的方式引入 Flutter Gradle 插件。切换新版本后,Flutter 的 Gradle 插件会直接拒绝老写法。

我踩过之后总结的解法分两步:

  1. 如果只是想回退到旧版本继续干活,直接fvm use 旧版本就能搞定,报错一般随之消失。
  2. 如果想留在新版本,得动 Gradle 配置,把 settings.gradle 里的pluginManagementpluginsDSL 按官方迁移文档调整。

这里其实体现出 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_HOMEPUB_CACHE这两个环境变量都指到非系统盘,并把旧的缓存目录手动清理掉。pub-cache 是个容易被忽略的大户,flutter 项目跑多了,这里轻松攒出几个 G 的依赖包。

4.4 版本切换后的连带问题速查表

问题可能原因快速处理
flutter 命令版本没变化PATH 未指向 fvm default确认%FVM_HOME%\default\bin已加入 PATH
VS Code 找不到 Flutter SDK项目没生成符号链接项目根目录执行fvm use <版本>
Windows 桌面编译失败缺少 VS C++ 工具链装 VS Build Tools 并确认 flutter doctor
pub 依赖解析异常pubspec.lock 被新版本改过还原 lock 文件并重新 pub get
C 盘空间不足SDK 和 pub 缓存在系统盘修改 FVM_HOME 和 PUB_CACHE 到其他盘
Gradle 插件报错Flutter 版本升级引起不兼容回退版本或迁移到 plugins DSL
fvm use 提示符号链接失败权限受限或开发者模式未开开启开发者模式或管理员终端执行

5. 一点进阶玩法:把 fvm 用出“云环境”的感觉

fvm 用熟之后,你会慢慢发现它不只是“切版本”的工具。因为版本配置文件是项目仓库的一部分,它可以被 CI/CD 直接读取。比如公司内部构建机只要装了 fvm,执行到项目目录时先fvm installfvm flutter build,构建环境就和本地完全一致了。这能省掉不少“本地能构建,服务器构建失败”的扯皮。

另外,fvm 也是做 Flutter 版本适配测试的最好助手。比如你写了一个插件,想知道它在 Flutter 3.13、3.16、3.19 下分别能不能编译,不用一个个手动调整全局 SDK,直接建三个目录分别锁不同版本,跑一遍就知道了。我甚至见过有人用脚本循环fvm use+flutter test来批量回归,效率非常高。

6. 总结我的使用心得

最后分享一点我自己的习惯。一开始我总觉得 fvm 是给团队协作才用的,个人开发者用不上,试过之后才发现这个想法很片面。就算只有一个项目,你也会有“想升级到新特性,但怕踩坑”的时候。fvm 最打动我的地方,是让升级这件事变成“可逆操作”:先切新版本跑两轮自动化测试,有问题一条命令退回旧版本,心里稳得多。

我现在的标准流程,每个项目不管大小都在根目录维护一份 fvm 版本配置并纳入版本管理。同事新 clone 下来,看一眼配置,执行fvm installfvm use就能复现环境。真别把小版本缓存全留着,每个稳定版两个 G,攒一年 C 盘直接爆,定期用fvm remove清掉不再用的版本,比清理什么 Windows 临时文件划算多了。

工具这个事,简单直接才撑得住长期用。fvm 在 Windows 上的价值,就是让你在 Flutter 多版本这个混乱问题上,找到一个足够简单、又足够可靠的支点。希望这篇实战记录能帮你少走一些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询