Post

VSCode 中 .NET 热重载配置详解

在 Visual Studio 中,热重载(Hot Reload)是开箱即用的。但在 VSCode 中,涉及到调试配置、任务配置和扩展的协作,稍不注意就会踩坑。本文梳理 VSCode 下 .NET 项目的调试配置体系,并重点说明热重载的正确开启方式。

VSCode 调试配置基础

VSCode 的调试体系由两个配置文件共同构成:.vscode/launch.json.vscode/tasks.json

launch.json:定义如何启动/附加调试器

launch.json 支持两种核心模式:

launch 模式:VSCode 直接启动进程并附加调试器。适合本地开发调试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": ".NET Core Launch (web)",
      "type": "coreclr",
      "request": "launch",
      "program": "${workspaceFolder}/bin/Debug/net8.0/MyApp.dll",
      "args": [],
      "cwd": "${workspaceFolder}",
      "env": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  ]
}

attach 模式:调试器附加到一个已经在运行的进程上。适合调试容器内进程、远程进程,或由其他方式启动的服务。

1
2
3
4
5
6
{
  "name": ".NET Core Attach",
  "type": "coreclr",
  "request": "attach",
  "processId": "${command:pickProcess}"
}

tasks.json:定义构建任务

tasks.json 中定义的任务可以在 launch 之前通过 preLaunchTask 触发,常见用法是先执行 dotnet build 再启动调试:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "command": "dotnet",
      "type": "process",
      "args": ["build", "${workspaceFolder}/MyApp.csproj"],
      "problemMatcher": "$msCompile"
    }
  ]
}

热重载的正确配置方式

关键结论

使用 C# Dev Kit 扩展时,不要在 launch.json 中设置 preLaunchTask

一旦配置了 preLaunchTask,C# Dev Kit 会认为你在自行管理构建流程,从而跳过热重载功能的注入。结果就是:程序能运行,调试器也能附加,但修改代码后没有任何热重载效果。

正确做法

C# Dev Kit 的默认调试方式有两种入口:

  • 解决方案资源管理器右键项目 → 启动调试
  • launch.json 中配置 type: dotnet 的启动项

两种方式本质相同。type: dotnet 的启动项配置项较少,基本只能指定启动项目,大多数行为由项目的 launchSettings.json 控制。

type 设置为 "dotnet"request 设置为 "launch"不添加 preLaunchTask

1
2
3
4
5
6
7
8
9
10
11
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch with Hot Reload",
      "type": "dotnet",
      "request": "launch",
      "projectPath": "${workspaceFolder}/MyApp.csproj"
    }
  ]
}

C# Dev Kit 识别到 type: dotnet + request: launch 的组合后,会在启动时自动执行构建,并注入 Hot Reload 支持,无需手动配置 preLaunchTask

通过 launchSettings.json 启用热重载

C# Dev Kit 默认调试行为会读取项目的 Properties/launchSettings.json。要确保热重载生效,需在对应的 profile 中添加 hotReloadEnabled

1
2
3
4
5
6
7
8
9
10
11
{
  "profiles": {
    "MyApp": {
      "commandName": "Project",
      "hotReloadEnabled": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

多目标框架项目的运行时选择

当项目配置了多目标框架(<TargetFrameworks>)时,Visual Studio 可以在调试栏手动切换运行时版本,但 VSCode 没有此入口。解决方法是修改 .csproj,将希望默认使用的框架版本放到最前面

1
2
<!-- 调试时将优先使用 net8.0 -->
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>

Razor View 的热重载

注意RazorRuntimeCompilation(RRC)的工作机制与 .NET 的 Hot Reload 并不相同——RRC 是在运行时重新编译 Razor 文件,而 Hot Reload 是在调试会话中直接更新托管代码。自 .NET 6 起,官方推荐优先使用 Hot Reload,不再推荐 RRC 作为主要的开发体验。以下配置仅在需要兼容旧方式或特定场景时使用。

对于 ASP.NET Core MVC / Razor Pages 项目,上面的配置只能热重载 C# 代码。.cshtml 文件的修改默认不会生效,需要额外配置运行时编译。

1. 安装 NuGet 包

1
dotnet add package Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation

2. 注册服务

1
2
builder.Services.AddControllersWithViews()
    .AddRazorRuntimeCompilation();

3. 条件编译,避免影响生产环境

运行时编译会带来额外开销,不应进入生产构建。使用条件编译将其限制在 DEBUG 模式:

1
2
3
4
5
var mvcBuilder = builder.Services.AddControllersWithViews();

#if DEBUG
mvcBuilder.AddRazorRuntimeCompilation();
#endif

4. 条件引入 NuGet 包(推荐)

为了让 RuntimeCompilation 包不出现在 Release 产物中,可以在 .csproj 中配置条件引入:

1
2
3
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
  <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0" />
</ItemGroup>

这样 Release 构建时既不会编译该包的依赖,也不会将其打入最终产物。与 #if DEBUG 搭配使用,既保证代码编译时不会因缺包报错,又能确保生产产物干净。


排查热重载问题:查看输出日志

如果热重载没有生效,可以在 VSCode 的输出(Output)面板中查看详细日志。

打开方式:菜单 → View → Output,然后在右侧下拉菜单中选择 C# Hot ReloadDebugger,即可查看热重载引擎和调试器的运行日志,确认热重载是否被正确注入,以及失败的具体原因。


小结

场景做法
C# 代码热重载type: dotnet + request: launch不设置 preLaunchTask
启用热重载launchSettings.json 对应 profile 中设置 hotReloadEnabled: true
需要自定义构建步骤preLaunchTask,但热重载将失效,需权衡
Razor View 热重载(旧方式)安装 RuntimeCompilation 包,条件注册服务(.NET 6+ 推荐改用 Hot Reload)
生产构建不含调试包.csproj 中用 Condition 条件引入包
多目标框架默认运行时.csproj<TargetFrameworks> 中将目标框架置于首位
热重载未生效时排查VSCode 输出面板 → 选择 C# Hot ReloadDebugger 查看日志

在 VSCode 下做 .NET 开发,调试配置的细节比 Visual Studio 多得多。理解 launch / attach 的区别、Dev Kit 的自动构建机制,以及热重载的注入时机,才能避免踩坑。

This post is licensed under CC BY 4.0 by the author.

Trending Tags