写过前端的人都踩过这个坑——页面加载只能等完整 HTML 到了才开始渲染,今天 Chrome 150 把这件事彻底零框架化了
一个内容繁多的页面,如果第三段内容依赖一个慢查询,整个页面就只能等——要么服务端 buffer 住全部响应放弃流式传输,要么用 CSS 硬排牺牲无障碍,要么接一个重量级前端框架专门处理这个场景。这是 HTML 二十年来从未改变的基本规则:HTML 按到达顺序渲染。
Chrome 150 稳定版引入的 Declarative Partial Updates,从根本上改变了这个约束——让浏览器可以在 HTML 到达时直接更新页面指定区域,无需等待完整文档,无需前端框架介入。核心分成两部分:声明式占位符和新版 JavaScript HTML 插入方法。
声明式部分更新的原理
第一部分用 XML 里早已存在、但在 HTML 里一直被浏览器忽略的处理指令(Processing Instruction)。Chrome 给它重新分配了一个角色:当解析器遇到 template data-href 时,会先渲染自身内容作为占位,然后当同一流的 template 到达时自动替换进去——中间不需要任何 JavaScript。
range 形式是最常用的写法:section 内放 template data-href,p 标签内写「加载中」作为占位内容。服务端返回带 data-href 的 template 时,浏览器自动完成替换。
更巧妙的是:template 可以重新发出自己的 data-href 标记,形成 append 循环——服务端每返回一行数据就带一个 marker,列表就会在原地逐行增长,不需要 appendChild,不需要框架,连 JavaScript 都不用写。
一个 marker 只能更新同一父元素内的占位符,这是出于安全考虑,防止跨文档注入。
新版 JavaScript 方法的重新设计
第二部分解决的是另一个历史遗留问题:之前 innerHTML、setHTML、setHTMLUnsafe、insertAdjacentHTML、createContextualFragment 五种方法行为不一致——哪些会覆盖、哪些追加、哪些执行脚本、哪些支持 Trusted Types,没有人能全部说清楚。
新方案用一套清晰的 API 网格替代:setHTML、beforeHTML、afterHTML、prependHTML、appendHTML、replaceWithHTML,每个都有静态版本和流式版本。普通版本默认走 sanitizer 清理,Unsafe 版本接受 runScripts: true 选项用于执行受信任的脚本。Unsafe 这个词是刻意加的提醒,不是禁止。
流式版本是真正的新能力:el.streamHTMLUnsafe() 返回 WritableStream,fetch 的响应体可以直接流进 DOM,pipeThrough TextDecoderStream 再 pipeTo 即可。这是 SPA 从未做到过的事——用标记语言表达的一整套组件路由切换逻辑。
对性能的实际影响
对性能工程师来说,这个 API 真正值得关注的点是 Time to Interactive 的改善。流式 HTML 注入让内容先有意义地展示出来,再逐步填充,而不是卡在框架的 hydrate 流程里等待。
下一步怎么做
目前 Chrome 150+ 已默认开启,无需 flag。WebKit 在 out-of-order streaming 方面已给出支持信号,Firefox 态度开放——三个引擎在收敛中。组件化前端值得本周开一个小 prototype,语法一下午可以验证完毕。
评论区
登录后可评论。