跳转至

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 异步