WebForms Core vs 现代 Web 概念:架构相似性与差异
Source: Dev.to
介绍
在大多数现代前端框架中,客户端是主要的决策者:它构建 UI、管理状态、执行数据获取并对变化作出响应。服务器通常仅充当 API 提供者。WebForms Core (WFC) 刻意颠倒了这种模型。在 WFC 中,服务器充当编排者,发出明确的 UI 和行为指令,而 WebFormsJS 在客户端自动执行这些指令。
本文 不 旨在提供一个简单的功能清单。相反,它解释了 WebForms Core 在架构层面上如何与现代 Web 概念保持一致、产生分歧,或有意对立。
在传统的 WebForms 架构中,每一次客户端事件都需要向服务器发送完整页面请求。这种做法导致带宽消耗大、响应速度慢。WebForms Core 在这方面引入了根本性的革命,即其 基于命令的通信 架构。
一个 WebForms Core 项目由两大部分组成:
| 部分 | 描述 |
|---|---|
| 视图 | HTML 文件或 Razor 页面 |
| 控制器 | 用于事件管理的服务器端类 |
视图 (Index.cshtml 或 index.html)
@page
@controller TextBoxController
Change TextBox Color
服务器端控制器 (TextBoxController.cs)
using CodeBehind;
public partial class TextBoxController : CodeBehindController
{
public void PageLoad(HttpContext context)
{
// Check if keyup parameter exists in QueryString
if (context.Request.Query.ContainsKey("keyup"))
{
TextBox_keyUp();
return;
}
// Set up events in initial page load
WebForms form = new WebForms();
form.SetGetEvent("TextBox1", HtmlEvent.OnKeyUp, "?keyup");
Write(form.ExportToHtmlComment());
}
private void TextBox_keyUp()
{
WebForms form = new WebForms();
// Get the value entered by the user
string colorValue = Fetch.GetValue("TextBox1");
// Set the background color of TextBox1
form.SetBackgroundColor("TextBox1", colorValue);
// Set cache for one year (31536000 seconds)
form.SetCache(31536000);
// Send response (this is NOT an HTML comment, it's INI text)
Write(form.Response());
// Ignore View and Layout
IgnoreAll();
}
}
第一期 – 初始页面请求
- 用户导航到页面 URL。
- 服务器调用控制器并执行
PageLoad。 - 因为查询字符串中 没有
keyup参数,条件块被跳过,事件‑设置代码运行:
WebForms form = new WebForms();
form.SetGetEvent("TextBox1", HtmlEvent.OnKeyUp, "?keyup");
Write(form.ExportToHtmlComment());
ExportToHtmlComment生成一个嵌入页面的 HTML 注释(在本例中注释本身为空)。- 发送给浏览器的完整响应如下所示:
Change TextBox Color
web-forms.js 脚本读取该注释并为 #TextBox1 附加一个 keyup 监听器。
第二阶段 – 用户交互(KeyUp 事件)
当用户在文本框中输入(例如 “red”)时,web-forms.js 会向注释中定义的 URL 发送 Ajax 请求:
GET /page?keyup&TextBox1=red HTTP/1.1
第三阶段 – 服务器上的请求处理
控制器再次被调用。这一次查询字符串 包含 keyup,于是运行以下方法:
private void TextBox_keyUp()
{
WebForms form = new WebForms();
// Get the value "red" from the TextBox1 parameter
string colorValue = Fetch.GetValue("TextBox1");
// Set TextBox1 background color to red
form.SetBackgroundColor("TextBox1", colorValue);
// Set cache for one year (31536000 seconds)
form.SetCache(31536000);
// Send response (INI pattern without HTML comment wrapper)
Write(form.Response());
// Ignore View and Layout
IgnoreAll();
}
Response() 生成纯文本(INI‑风格)输出,不 包含 HTML 注释包装:
[web-forms]
bcTextBox1=@$vTextBox1
cd=31536000
脚本接收这段原始文本并直接进行解析。
Phase Four – Receiving and Executing Commands in the Browser
web-forms.js interprets the response:
| Command | Meaning |
|---|---|
bcTextBox1=@$vTextBox1 | 将 ID 为 TextBox1 的元素的背景颜色设置为用户提供的值(red)。 |
cd=31536000 | 在浏览器中将页面缓存 31 536 000 秒(即一年)。 |
After executing the commands:
- 文本框的背景会立即变为 red,且无需完整页面刷新。
- 页面将被缓存一年。
第五阶段 – 随后页面请求
当用户重新访问页面时:
- 浏览器从其 本地缓存 加载页面(得益于
cd=31536000指令)。 - 不会向服务器发送请求。
- 注册
keyup事件的[web-forms]注释仍然保留在缓存的 HTML 中,因此所有客户端事件仍然可用。
通信流程概述
| 步骤 | 客户端操作 | 服务器操作 | 响应类型 |
|---|---|---|---|
| 1️⃣ 初始加载 | 请求页面 | PageLoad → 注册事件 | HTML 注释 (<!-- … -->) |
| 2️⃣ 事件(keyup) | 使用 ?keyup 参数和字段值的 Ajax GET | TextBox_keyUp → 构建命令 | 纯 INI 文本 ([web-forms]…) |
| 3️⃣ 浏览器 | 解析 INI,应用 UI 更改,设置缓存 | — | — |
| 4️⃣ 后续加载 | 从缓存提供 | — | — |
通信细节
初始请求
HTML 注释 <!-- … --> – 嵌入在 HTML 中以 注册事件。
后续响应
| 类型 | 描述 |
|---|---|
纯文本 (INI) [web‑forms] … | 包含 UI 命令和缓存指令。 |
| 原始响应体 | 由客户端执行以应用更改并设置缓存。 |
关键区别: 只有 初始事件注册 以 HTML 注释的形式发送。客户端与服务器之间的所有运行时交互均使用 纯文本响应,从而最小化带宽和解析开销。
好处
- 最小的带宽消耗
- 显著降低服务器负载
- 流畅快速的用户体验
- 智能缓存策略 – 第一次用户交互后,动态内容能够正常工作,而后续访问则受益于即时加载。开发者可以完全控制缓存时长。
- 实现简便 – 无需繁重的 SPA 框架、复杂的状态管理或独立的 RESTful API。
- 兼容 MVC 架构 – 示例可以一步完成;评论仅发送一次,记录事件并携带执行指令。
示例 (C#)
using CodeBehind;
public partial class TextBoxController : CodeBehindController
{
public void PageLoad(HttpContext context)
{
WebForms form = new WebForms();
form.SetCommentEvent("TextBox1", HtmlEvent.OnKeyUp, "keyup");
form.StartIndex("keyup");
form.SetBackgroundColor("TextBox1", Fetch.GetValue("TextBox1"));
Write(form.ExportToHtmlComment());
}
}
WebForms Core 非常灵活:您可以根据需要采用 以客户端为中心 或 以服务器端为中心 的架构。这种灵活性是它最大的优势。
架构概览
实时通信
- Server‑Sent Events (SSE) – 打开 HTTP 连接以增量发送 UI 指令。
- WebSocket 支持(实现必须由服务器提供)。
注意: 支持 SSE 和 WebSocket,但底层基础设施必须由服务器实现。
渲染
- SSR(服务器端渲染) 开箱即用 – 首屏渲染快速,友好 SEO。后续更新通过服务器下发的目标指令完成,而不是完整页面重新加载。
- 客户端渲染 也是可能的,但并非传统的 SPA 方式;渲染决策仍由服务器驱动。
- 无 hydration – 初始请求返回 HTML +
WebFormsJS。后续交互仅返回 HTML 片段或动作‑控制指令,降低客户端 CPU、JS 复杂度和内存占用。
静态站点生成
由于 WFC 能生成确定性的 HTML,它能够很好地融入静态站点工作流:页面可以预渲染,随后在有网络时通过服务器驱动的交互进行增强。
类 SPA 体验
- 没有完整页面刷新,仅进行局部更新。
- 导航、路由和更新由服务器编排(而非客户端拥有的 SPA)。
客户端路由
指向内部路由的锚点会被自动拦截,防止页面刷新,并将导航委派给服务器驱动的指令管线。
架构立场
- Headless 架构(渲染与内容/逻辑分离)被 拒绝。服务器同时提供数据 和 展示/行为,集中控制并降低前端复杂度。
- 与 Islands Architecture 有相似之处:并非页面的所有部分都同等交互。但 WFC 的交互是 服务器管理的 UI 区域,而非孤立的 JavaScript 小岛。相较于传统的基于岛屿的系统,切换 WFC 的服务器框架往往比迁移前端框架更容易。
状态管理
- 状态自动在服务器上管理。
- 开发者可以选择使用
AddState等机制存储瞬时客户端状态,但整体生命周期仍由服务器治理。
绑定模型
- 命令式、指令驱动的绑定 – 数据通过显式的服务器指令注入到 HTML 元素中,区别于现代框架中声明式/响应式的数据绑定。
URL 与数据映射
- 基本上是自动的,符合早期 Web 的原则。
- 高级路由场景可以通过 基于 Service 的 扩展实现。
Source: …
WebForms Core (WFC) 概览
- 服务器驱动的 UI 编排 – 交互是事件驱动且由服务器触发,产生的惰性加载响应仅包含所需指令。
性能与压缩
- Gzip 压缩 可在服务器端和客户端同时使用。
- 紧凑的指令格式相比传统基于 JSON 的 API 进一步降低了负载大小。
- 在 WebForms Core 中,文件和表单数据都可以使用 gzip 压缩发送。解压由 服务器负责,即解压
WebFormsJS发送的 gzip。
DOM 处理
- WFC 不实现虚拟 DOM 或 diff 算法。
- 它采用 瞬态 DOM 方法:
- 克隆目标元素。
- 应用多项更改。
- 在一次操作中提交。
- 这可以防止闪烁并提升感知性能。
渐进式 Web 应用 (PWA) 支持
- WFC 通过 Service Workers 和 Web App Manifests 完全支持 PWA 功能。
- 离线行为、可安装性和缓存策略可在 不改变核心架构 的前提下进行管理。
组件模型
- WFC 不实现真正的 Web Components(自定义元素、Shadow DOM)。
- 可通过以下方式 模拟 可复用组件:
- 服务器端模板
- HTML 片段
- 扩展方法
WebAssembly 集成
- 当需要时,WFC 可以 从客户端调用 WebAssembly 模块,实现高性能操作而无需更改整体编程模型。
浏览器 API 访问
- 对浏览器 API(如 摄像头、蓝牙或文件系统)的直接访问 未内置在 WFC 核心。
- 这些功能可在需要时 通过自定义 JavaScript 模块 启用。
无状态与可扩展架构
- WebForms Core 完全 无状态,兼容无服务器架构。
- 它可无缝运行于负载均衡器后端以及水平扩展的环境中。
测试策略
- 测试主要 聚焦于服务器端。
- 由于客户端逻辑极少且协议稳定,单元测试更简单、更确定。
- 通信契约由框架本身维护,降低了客户端测试的复杂度。
CLI 与开发集成
- WFC 不引入独立的 CLI。
- 它直接集成到现有的后端项目中。
- 开发仅需服务器端的
WebForms类,并在 HTML<script>标签中引入WebFormsJS。
架构哲学
- WebForms Core 现代化,但 不试图模仿现代前端框架。
- 它代表一种 不同的架构哲学:服务器驱动的 UI 编排,配合极简、服从的客户端。
- 许多现代 Web 概念得到支持,只是以根本不同的方式实现;其他则被有意舍弃。
定位与使用场景匹配
- 与其问 WFC 是否属于 JAMstack、Headless 或 Reactive SPA 等已有类别,不如问它的 服务器指令模型是否符合项目目标。
- 对于寻求以下目标的团队:
- 降低前端复杂度
- 集中化控制
- 可预测的行为
- WebForms Core 提供了一种独特且连贯的替代方案。