Transform(编译变换阶段)

编译器对 AST 进行遍历和修改的阶段,是前端框架编译优化的核心战场。各框架的编译差异主要体现在 Transform 阶段——Vue 注入 Patch Flags 和静态提升标记,Svelte 生成响应式绑定代码,React Compiler 划分缓存区域,Qwik 提取闭包做代码拆分。

核心概念

Transform 是编译管线三阶段(Parse → Transform → Codegen)的中间环节。Parse 产出 AST 后,Transform 对 AST 做一系列变换 pass(遍历 + 修改),注入优化标记或重写节点结构,为最终的 Codegen(代码生成)提供优化后的中间表示。

Transform 是"编译器的三重身份"(消灭 diff / 加速 diff / 推迟加载)的核心分界线——同一段源码经过不同框架的 Transform 后,AST 上携带的优化信息完全不同,决定了 Codegen 输出什么样的目标代码。

各框架的 Transform 策略

Svelte 5

  • 模板静态分析:识别哪些模板绑定是静态的(编译期可确定依赖)、哪些需要运行时追踪
  • 响应式绑定生成:$state 标记的变量被转换为 signal 原语调用($.source),模板中的 {count} 被转换为 $.template_effect(() => set_text(text, $.get(count))) 的精确 DOM 更新
  • 事件委托转换:onclick 被转换为 element.__click 的委托式处理

Vue 3

  • Patch Flags 注入:在 VNode 创建调用中添加位标记参数(如 2 /* CLASS */),告诉运行时 diff 只需检查标记的属性
  • 静态提升(Static Hoisting):将不含动态绑定的 VNode 提升到渲染函数外部,标记为 HOISTED = -1
  • Block Tree 优化:用 openBlock + createBlock 创建扁平化的动态节点数组,将 diff 复杂度从 O(模板大小) 降到 O(动态节点数)

React Compiler

  • HIR(高级中间表示)构建:将组件函数的控制流转换为 SSA 形式
  • 响应式值推导:分析哪些值是"响应式的"(来自 props / state / context),哪些是纯计算可缓存的
  • 缓存区域划分:将组件函数体切分为多个作用域,每个作用域对应一个缓存槽位($[n]),只有当作用域的依赖值变化时才重新计算

Qwik Optimizer

  • $ 函数体提取:将 $ 后缀标记的函数体从当前模块中提取出来,生成独立的懒加载 chunk 引用
  • 闭包变量分析:遍历被提取函数体的 AST,收集所有捕获的外部变量,为 useLexicalScope 的序列化/反序列化生成胶水代码
  • 事件代理映射:将 onClick$ 转换为 HTML 属性字符串引用(on:click="chunk-xxx.js#handler_0"

Transform 是编译优化的核心战场

Parse 阶段各框架差异不大(都是把文本变成树),Codegen 阶段是机械地把优化后的 AST 转成目标代码——真正决定编译器"做了什么优化"的,是 Transform 阶段注入了什么信息、重写了什么结构。

框架Transform 核心工作优化目标
Svelte 5模板绑定→signal 直连 DOM消灭运行时 diff
Vue 3注入 Patch Flags + 静态提升加速运行时 diff
React Compiler缓存区域划分 + 依赖推导减少不必要的重渲染
Qwik函数体提取 + 闭包序列化分析推迟 JS 加载时机
SolidJSX→insert/cloneNode 转换消灭 diff(但依赖收集在运行时)

引用本术语的文章