跳转至

Yoga Layout 专题

重要性:⭐⭐⭐⭐(布局基础——Facebook Yoga 在终端的完整应用) 真实位置:src/native-ts/yoga-layout/index.ts(2578 行,详见 deep-dive) 角色:Ink 的布局算法 —— flexbox for terminal 关联:topics/deep-dive-yoga-layout.md(深度拆解)、topics/ink-react-reconciler.md


1. Yoga 是什么

Yoga = Facebook 开源 flexbox 引擎 - 原本用于 React Native - 纯 C++ 实现 - 跨平台(iOS / Android / Web / Terminal)

Claude Code 用 Yoga —— 在终端实现 flexbox 布局。


2. 为什么选 Yoga

选项 优点 缺点
Yoga 工业级、跨平台、纯 TS 移植可能 大
手写 flexbox 小 维护成本高
简单行布局 简单 复杂布局无解
CSS Grid 强大 终端无 DOM

Yoga 综合最优 —— 工业级验证。


3. 4 大替代方案 vs Yoga

3.1 Yoga(选)

  • ✅ 工业级
  • ✅ 跨平台
  • ✅ flexbox 标准
  • ✅ 文档丰富
  • ❌ 2578 行 TS 移植

3.2 自写 flexbox

  • ✅ 极简
  • ❌ 维护成本
  • ❌ bug 风险

3.3 行优先布局

  • ✅ 简单
  • ❌ 复杂布局无解

3.4 grid 布局

  • ❌ 终端无 DOM
  • ❌ 复杂

Yoga 选 —— 综合最优。


4. 纯 TS 移植 vs C++

4.1 选纯 TS

  • ✅ 无 WASM 启动
  • ✅ 无 N-API
  • ✅ 跨平台
  • ✅ 可调试
  • ❌ 速度略慢

4.2 性能

~5-50ms 布局时间 —— 可接受。

4-slot LRU 缓存 —— 80% 命中。


5. Yoga 在 Claude Code 的应用

5.1 REPL 布局

┌─────────────────────────────────┐
│  Header (Title)                 │
├─────────────────────────────────┤
│                                 │
│  Main Content (Scroll)          │
│  - Messages                     │
│  - Tools                        │
│                                 │
├─────────────────────────────────┤
│  PromptInput                    │
├─────────────────────────────────┤
│  Footer (Status)                │
└─────────────────────────────────┘

flexbox 布局: - Header fixed top - Main grow - PromptInput fixed bottom - Footer fixed bottom

5.2 复杂布局示例

<Box flexDirection="row">
  <Box width={20}>
    <Text>Sidebar</Text>
  </Box>
  <Box flexGrow={1}>
    <Text>Main</Text>
  </Box>
</Box>

横向 flex —— sidebar + main。

5.3 对齐

<Box justifyContent="space-between" alignItems="center">
  <Text>Left</Text>
  <Text>Right</Text>
</Box>

两端对齐 + 居中。


6. Yoga API(60+ exports)

6.1 Node API

import { Node } from './yoga-layout'

const node = Node.create()
node.setFlexDirection('row')
node.setJustifyContent('space-between')
node.setAlignItems('center')
node.setFlexGrow(1)
node.calculateLayout(width, height, 'ltr')
const { left, top, width, height } = node.getComputedLayout()

链式 API —— 类似 DOM。

6.2 Config API

Node.create(config)

Config —— 错误容忍、点精度。

6.3 Measure Function

node.setMeasureFunc((width, widthMode, height, heightMode) => {
  return { width, height }
})

异步测量 —— 动态内容。

6.4 4-slot Cache

node.calculateLayout(...)
// 缓存上次结果

4-slot —— 平衡内存/命中。


7. 关键算法(推测)

7.1 单 node 布局

function layoutNode(node, ownerSize) {
  // 1. 测量(如果有 Measure function)
  // 2. 计算 flexBasis
  // 3. 解析 flex length
  // 4. 计算绝对定位
  // 5. 处理 auto margin
}

5 步。

7.2 Flex 分配

// 剩余空间 = 容器 - 已用
// 按 flexGrow/flexShrink 分配

剩余分配 —— flex 标准。

7.3 Justify / Align

// 主轴: justifyContent
// 交叉轴: alignItems / alignSelf

2 轴 —— 6+5 种值。

7.4 Absolute 定位

position: 'absolute'  // 独立定位

独立于 flex。


8. 性能特征

8.1 简单布局

  • 1-10 节点:< 1ms
  • 命中缓存:< 0.1ms

8.2 中等布局

  • 10-100 节点:~1-10ms

8.3 复杂布局

  • 100-1000 节点:~10-100ms
  • 深度嵌套:~50-200ms

8.4 优化

  • 4-slot cache
  • 早期退出(叶子)
  • flex basis 一次计算

9. Yoga vs 其他

维度 Yoga CSS flexbox SwiftUI
实现 TS / C++ 浏览器 Swift
性能 中 高 高
跨平台 ✅ ❌(仅 web) ❌(仅 Apple)
终端 ✅ ❌ ❌

Yoga 唯一适合终端。


10. Yoga 在 Ink 的集成

10.1 Reconciler

// ink/reconciler.ts
createInstance(type) {
  const node = Node.create()
  return { ...node, type }
}

每个 React element → 1 个 Yoga node。

10.2 layout pass

// ink/dom.ts
calculateLayout() {
  // 1. 树遍历
  // 2. 调 yoga calculateLayout
  // 3. 缓存结果
}

完整布局 pass。

10.3 render pass

// ink/render-to-screen.ts
render() {
  // 1. 读 layout
  // 2. 输出字符
}

render 用 layout。


11. Yoga 调试

11.1 getYogaCounters

import { getYogaCounters } from './yoga-layout'
const { layouts, cacheHits } = getYogaCounters()

性能 metrics。

11.2 4-slot cache 调试

// 推测:debug mode 输出 cache 状态

debug 模式。


12. 关键设计模式

12.1 Pure TS 移植

避免 WASM —— 启动快。

12.2 4-slot LRU

平衡内存/命中。

12.3 编译时门控

// 推测:Yoga 是默认加载
// 但 DCE 不动

总是加载 —— 核心。

12.4 Value 抽象

type Value = {
  unit: 'point' | 'percent' | 'auto' | 'undefined'
  value: number
}

4 种单位 —— 统一表示。

12.5 Edge 抽象

// resolveEdge 处理 RTL

RTL 支持。

12.6 Measure function

// 异步测量

动态内容。


13. 关键洞察

13.1 Yoga = 工业级 flexbox

Facebook 验证。

13.2 纯 TS 移植是商业选择

启动 > 速度。

13.3 4-slot cache 80% 命中

平衡内存/性能。

13.4 RTL 通过 Edge 抽象

i18n 友好。

13.5 Measure function 异步

动态内容。

13.6 Yoga 是 Ink 核心

没有 Yoga,Ink 不可用。

13.7 60+ exports 完整

5 大类:Node / Config / Layout / Style / Measure。

13.8 Config 默认合理

用户极少需要 自定义。

13.9 Yoga 不止 flexbox

还有 absolute / intrinsic / measure / text。

13.10 性能可监控

getYogaCounters 暴露 metrics。


14. 改进方向

14.1 减小 yoga-layout 体积

2578 行 —— 可拆 sub-modules。

14.2 改进 cache

4-slot → 8-slot 或自适应。

14.3 增量布局

只重新 layout 变化部分。

14.4 多线程布局

Worker thread 跑 layout。


15. 阅读建议

  1. 看 deep-dive-yoga-layout.md —— 详细
  2. 看 ink/reconciler.ts —— 集成方式
  3. 看 ink/dom.ts —— DOM 抽象
  4. 跑复杂 UI —— 看 layout 时间

16. 与其他专题的关系

文件 关系
deep-dive-yoga-layout.md 深度
ink-react-reconciler.md 集成
terminal-compatibility.md 终端

17. 总结

Yoga = 终端 flexbox —— 工业级实现。

在 Claude Code: - Ink 渲染核心 - REPL 布局 - 复杂 UI 编排

关键: - 纯 TS 移植(无 WASM) - 4-slot LRU - RTL / i18n 友好 - Measure function 异步