← 中文资源

简体中文版本

服务端渲染水合

水合把事件监听器与框架状态挂到服务端渲染的 HTML 上,使其无需重新渲染即可交互;客户端与服务端标记必须精确匹配。

阅读英文原文

概念定义

服务端渲染让像素快速出现,交互性则需要把监听器与状态挂到那份 DOM 上。水合就是“挂”这一步:框架对既有节点重新执行组件而不是重建。用户先看到内容,水合完成后才可交互。

工作机制

客户端按服务端渲染的相同顺序遍历 DOM,逐节点断言与自己会产出的结果一致:匹配则收养既有节点,不一致则客户端重渲染。选择性水合与渐进水合优先处理可见或交互区域;岛屿架构则完全跳过其余部分。

使用场景

既要快首绘又要交互的站点。静态为主的页面适合岛屿或零 JS;应用型页面接受全量水合,因为整棵树本来就要交互。真正移动的指标是可交互时间与交互延迟。

常见误区

水合并非免费:遍历并绑定大树的主线程时间与页面体积成正比。不匹配的后果不是“自动修复”而是丢弃服务端节点重渲染,抹掉该子树的 SSR 收益。时间戳、本地化格式、按环境不同的特性开关是经典不匹配来源;第三方脚本在水合前改动 DOM 同样会破坏框架假设。

代码示例

public class StringBuilderManipulation {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder(64);

        sb.append("Hello");
        sb.append(" ");
        sb.append("World");
        System.out.println("Built: " + sb);

        sb.insert(5, " Java");
        System.out.println("After insert: " + sb);

        sb.delete(5, 10);
        System.out.println("After delete: " + sb);

        sb.replace(0, 5, "Hi");
        System.out.println("After replace: " + sb);

        sb.reverse();
        System.out.println("Reversed: " + sb);

        String csv = String.join(", ",
            "Apple", "Banana", "Cherry", "Date");
        System.out.println("CSV: " + csv);

        String formatted = String.format(
            "Name: %s, Age: %d, Score: %.2f",
            "Alice", 30, 95.5
        );
        System.out.println(formatted);

        String stripped = "  padded  ".strip();
        System.out.println("Stripped: '" + stripped + "'");
    }
}