Blazor vs React:.NET 开发者的诚实比较
Source: Dev.to
什么是 Blazor?
Blazor 是微软的框架,用 C# 而不是 JavaScript 来构建交互式 Web UI。名字是 Browser(浏览器)和 Razor(.NET 模板语法)的组合,自 2020 年起已进入生产环境。
核心思想是你编写的 C# 可以:
- 在服务器上运行(Blazor Server) – 你的 C# 在服务器上执行,UI 更新通过 SignalR WebSocket 实时推送到浏览器。
- 在浏览器中运行(Blazor WebAssembly) – .NET 运行时本身通过 WebAssembly 在浏览器中运行。是的,实际编译后的 .NET 代码在浏览器里运行。
- 两者兼顾(Blazor United/.NET 8+) – 按组件选择渲染模式。服务器端用于首屏加载速度,WebAssembly 用于离线能力。两全其美。
// 一个 Blazor 组件。是的,这就是 UI 中的 C#。
@page "/counter"
<h2>Counter</h2>
<p>Current count: @currentCount</p>
<button @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
就是这么简单。没有 webpack。没有 Babel。没有成百上千的配置文件。只有可以编译并运行的 C#。
对 React 的质疑
React 本身没问题。它开创了基于组件的 UI,Virtual DOM 也相当聪明。Facebook 在用,而且看起来还不错。
然而,在多年构建生产级 React 应用后,我开始注意到一些让我怀疑人生的模式:
- 生态系统不断变化 – 每年都会出现一种“正确的”做法。
| 年份 | 当下流行的状态管理 |
|---|---|
| 2016 | Redux(显而易见) |
| 2018 | MobX(Redux 太冗长!) |
| 2020 | Context API(谁还需要库?) |
| 2021 | Zustand(Context 不够扩展!) |
| 2022 | Jotai、Recoil、Valtio… |
| 2024 | Server Components(状态是谎言?) |
-
工具过载 – 启动一个新的 React 项目意味着在编写任何业务代码之前,需要在数十种打包工具、状态管理库、样式方案、数据获取工具、表单库以及元框架之间做选择。
-
TypeScript 的局限 – TypeScript 只是对动态类型语言的临时补丁。类型仅在编译时提供建议,运行时验证仍需手动完成。
// TypeScript:类型其实只是建议
const user: User = JSON.parse(response); // 没有运行时验证!
// 而在 C# 中:
var user = JsonSerializer.Deserialize(response); // 实际的反序列化并进行类型检查
node_modules的安全隐患 – 庞大的依赖树和志愿维护者模式让 npm 生态容易受到供应链攻击。
npm 灾难精选
| 事件 | 年份 | 影响 |
|---|---|---|
| left‑pad | 2016 | 一位开发者撤下了一个 11 行的包。Babel、React 以及成千上万的项目瞬间崩溃。 |
| event‑stream | 2018 | “好心”新维护者注入恶意代码,2.5 个月未被发现,目标是比特币钱包。 |
| ua‑parser‑js | 2021 | 每周 800 万次下载。被劫持后会安装加密矿工和密码窃取器。 |
| everything | 2024 | 一个“玩笑”包依赖了所有 npm 包,安装它的任何人都会被 DoS。 |
| Shai‑Hulud | 2025 | 超过 26 亿次每周下载受影响。AI 辅助攻击,带有数据破坏载荷。 |
为何屡屡发生
- 巨大的依赖树 – 一个典型的 React 应用拥有数百个传递依赖,每一个都是攻击面。
- 志愿维护者 – 关键基础设施往往由无偿个人维护,容易被钓鱼或社会工程攻击。
- 缺乏构建时验证 – npm 只会安装
package.json中声明的内容,缺少编译时安全检查。 - 微小包的泛滥 – 生态系统把依赖微小工具(
is‑odd?、is‑even?)视为常态,累计形成巨大的攻击面。
一个“简单”React 项目的真实 npm 审计结果:
found 47 vulnerabilities (12 moderate, 28 high, 7 critical)
代码对比:React vs Blazor
React(使用 hooks)
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h2>Counter</h2>
<p>Current count: {count}</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
Blazor
@page "/counter"
<h2>Counter</h2>
<p>Current count: @count</p>
<button @onclick="() => count++">Click me</button>
@code {
private int count = 0;
}
两个示例在行数上相似,但 Blazor 版本没有 import、没有 useState hook,也不需要单独的 setter——只用一个普通变量和自增即可。
为什么 Blazor 适合我
- 零 npm audit 噩梦 –
dotnet list package --vulnerable通常返回零结果。 - 签名包 – NuGet 包可以进行加密签名。
- 精选生态 – 包的总量更少,但平均质量更高。
- 微软背书 – 核心库由万亿美元公司维护,而非个人开发者。
- 编译时安全 – C# 编译器在运行前捕获大量问题。
- 更小的依赖图 – .NET 完整的标准库降低了对外部包的需求。
Blazor 的演进:.NET 8、9、10
- .NET 8 引入 Blazor United,允许按组件选择渲染模式(Server vs WebAssembly)。
- .NET 9 增强了 Hot Reload,加速 UI 迭代。
- .NET 10(预览)承诺与 MAUI 更紧密的集成以及 WebAssembly 的 类原生性能。
React 仍然有价值的场景
- 需要 庞大的现有 JavaScript 生态 或 尚未移植到 Blazor 的第三方 React 组件 的项目。
- 团队拥有深厚的 JavaScript 专业技能,而 C# 经验有限。
- 必须 仅客户端渲染,且在浏览器中运行 .NET 运行时的开销不可接受的情况。
开始使用 Blazor
-
安装 .NET SDK(≥ 8.0)。
-
创建新项目:
dotnet new blazorwasm -o MyBlazorApp -
运行应用:
cd MyBlazorApp dotnet run -
在浏览器打开
https://localhost:5001并查看默认模板。 -
通过创建
.razor文件(例如Counter.razor)添加新页面,遵循前面展示的组件模式。
FAQ:常见疑问解答
问:我需要学习 Razor 语法吗?
答:是的,但它是 HTML 与 C# 代码块的自然扩展。对熟悉 C# 的人来说学习曲线很平缓。
问:性能如何比较?
答:Blazor WebAssembly 的启动稍慢于纯 JS 包,但加载完成后运行时性能相当。Blazor Server 在客户端负载极小,几乎实现即时 UI 更新。
问:我能使用现有的 JavaScript 库吗?
答:完全可以。Blazor 提供 JavaScript 互操作(IJSRuntime),在需要时调用任意 JS 库。
问:SEO 怎么办?
答:服务器端渲染(Blazor Server 或预渲染的 WebAssembly)会向爬虫返回完整的 HTML,提升 SEO 表现。
结语
从 React 转向 Blazor 为我带来了单语言栈,极大降低了依赖相关的安全风险,并简化了开发工作流。React 仍是强大的工具,尤其在你被 JavaScript‑中心生态锁定时。但对于追求更紧密集成、编译时安全以及更可预测依赖图的 .NET 开发者而言,Blazor 是一个极具吸引力的替代方案。