Glittering's blog Glittering's blog
Home
  • 学习手册

    • 《TypeScript教程》
    • 《Git》
    • 《Vite》
    • 《Vue3》
    • 《React18》
    • 《CSS》
    • 《Tailwind CSS》
    • 《JavaScript教程》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)

Glitz Ma

前端开发工程师
Home
  • 学习手册

    • 《TypeScript教程》
    • 《Git》
    • 《Vite》
    • 《Vue3》
    • 《React18》
    • 《CSS》
    • 《Tailwind CSS》
    • 《JavaScript教程》
    • 《ES6 教程》
    • 《TypeScript 从零实现 axios》
  • 技术文档
  • 算法
  • 工作总结
  • 实用技巧
  • collect
About
  • Classification
  • Label
GitHub (opens new window)
  • CSS

    • CSS教程和技巧收藏
    • css块元素和行内元素
    • 盒子模型
    • BFC和IFC
    • 字体font-weight相关知识
    • CSS-function汇总
    • CSS3之has函数的使用
    • CSS3之transition过渡
    • CSS3之animation动画
    • css动画性能优化
    • flex布局语法
    • flex布局案例
    • Grid布局语法
    • Flex 布局的性能讲透
    • flex布局和grid布局的区别
    • 「布局技巧」图片未加载前自动撑开元素高度
    • shadcn/ui学习笔记
    • shadcn/ui CVA 是什么
    • shadcn/ui radix ui 讲解
    • LayoutNG 是如何优化 Flex 的
      • 一、背景:为什么需要 LayoutNG?
      • 二、旧版 Flex 的性能问题
        • 1️⃣ 重复测量(Repeated Measurement)
        • 2️⃣ 回流传播不可控
        • 3️⃣ 不统一的 Layout Tree
        • 4️⃣ 浮点误差问题
      • 三、LayoutNG 的核心设计思想
        • 1️⃣ Constraint Space(约束空间)
        • 性能意义:
        • 2️⃣ Fragment Tree(片段树)
        • 3️⃣ 单向数据流
      • 四、LayoutNG 如何优化 Flex ?
      • 1️⃣ 减少测量次数
      • 2️⃣ 更聪明的 Free Space 分配算法
      • 3️⃣ 避免嵌套爆炸
      • 4️⃣ 更精准的 Dirty 标记
      • 5️⃣ 改进 min/max content 计算
      • 五、性能对比(真实趋势)
      • 六、LayoutNG 的一个关键突破
      • 七、为什么现在 Flex 不再是性能黑洞?
      • 八、你可以如何验证?
      • 九、终极总结
    • min-content 仍然是 Flex和Grid 最大的性能风险
    • h5适配方案
    • 前端1px的几种实现方案
    • 文字在一行或多行时超出显示省略号
    • 水平垂直居中的几种方式-案例
    • 如何根据系统主题自动响应CSS深色模式
    • 工作中遇到的css问题记录
    • 今天总结一下用到的css吧
  • 页面
  • CSS
mamingjuan
2025-10-10
目录

LayoutNG 是如何优化 Flex 的

# 一、背景:为什么需要 LayoutNG?

在 2020 年前,Chrome 使用旧版 Blink Layout。

问题:

  • 布局代码 20+ 年历史包袱
  • Block / Table / Flex / Grid 各自实现
  • 回流传播不可控
  • 嵌套 flex 容易重复计算
  • 浮点误差导致反复 layout

为了解决这些问题,Chromium 重写了布局引擎:

LayoutNG

它是 Chromium/Blink 的下一代布局系统。

目标:

  1. 更高性能
  2. 更少重复 layout
  3. 可预测的复杂度
  4. 更精确的规范实现

# 二、旧版 Flex 的性能问题

旧算法的问题主要有 4 类:


# 1️⃣ 重复测量(Repeated Measurement)

旧实现里:

  • flex-basis:auto
  • min-content
  • shrink

都会导致:

👉 子元素被测量多次

流程类似:

测量 → 分配空间 → 不够 → 重新测量 → 再分配
1

嵌套 flex 会指数级放大。


# 2️⃣ 回流传播不可控

在旧 Blink:

  • 父容器尺寸变化
  • 可能触发所有子元素重新 layout
  • 子元素变化又可能影响父元素

形成:

Layout Ping-Pong


# 3️⃣ 不统一的 Layout Tree

旧系统中:

  • Block 用一套逻辑
  • Flex 用另一套
  • Table 用另一套

共享能力弱 → 代码重复 → 优化困难


# 4️⃣ 浮点误差问题

空间分配后出现:

  • 1px 偏差
  • 再次 reflow 修正

导致额外 layout pass


# 三、LayoutNG 的核心设计思想

LayoutNG 引入了三大核心结构:


# 1️⃣ Constraint Space(约束空间)

核心思想:

子元素不再“自己猜尺寸” 而是父元素给一个明确约束空间

它包含:

  • 可用宽度
  • 可用高度
  • writing mode
  • min/max

这样:

子元素 layout 是纯函数:

输入:Constraint Space
输出:Fragment
1
2

# 性能意义:

  • 避免反复测量
  • 同样输入不会重复计算
  • 结果可缓存

# 2️⃣ Fragment Tree(片段树)

旧版 layout 直接修改 render tree。

LayoutNG:

  • 不直接修改节点
  • 生成 Fragment
  • 所有 layout 结果写入 fragment tree

好处:

  • 不污染原始结构
  • 可以回滚
  • 可以缓存
  • 避免重复遍历 DOM

# 3️⃣ 单向数据流

旧版:

父 → 子
子 → 父
父再 → 子
1
2
3

LayoutNG:

父传约束 → 子返回结果
结束
1
2

强制单向流动。

这和 Transformer 的单向 attention 有点类似 —— 避免循环依赖。


# 四、LayoutNG 如何优化 Flex ?

现在讲重点。


# 1️⃣ 减少测量次数

旧版:

for each item:
   measure min-content
   measure max-content
1
2
3

LayoutNG:

  • 只在真正需要时测量
  • 结果缓存
  • Constraint 相同直接复用

等价于:

memoization
1

复杂度从可能 O(n²) 降为接近 O(n)


# 2️⃣ 更聪明的 Free Space 分配算法

Flex grow/shrink 是最复杂部分。

LayoutNG 做了:

  • 预计算冻结项
  • 分批分配
  • 避免反复回退

旧版可能:

分配 → 溢出 → 回退 → 再分配
1

新版:

计算一次权重 → 批量分配
1

避免多轮 pass


# 3️⃣ 避免嵌套爆炸

旧版嵌套:

Flex
 └ Flex
    └ Flex
1
2
3

每层都重新 layout 子树。

LayoutNG:

  • 子树 layout 结果封装为 Fragment
  • 父层只读取尺寸
  • 不重新展开子树

这极大降低嵌套成本。


# 4️⃣ 更精准的 Dirty 标记

旧系统 dirty 粒度粗:

一个属性变 → 整个 subtree layout
1

LayoutNG:

  • 精确记录受影响节点
  • 使用 LayoutInvalidationReason
  • 只重新 layout 必要节点

例如:

改变某个 flex item 的 margin:

只影响:

  • 该 item
  • 该 flex container

而不是整个页面


# 5️⃣ 改进 min/max content 计算

min-content 是 Flex 性能杀手。

LayoutNG:

  • 使用统一 intrinsic sizing 算法
  • 避免重复测量
  • 使用更高精度 float 运算

减少回流次数。


# 五、性能对比(真实趋势)

在 Chromium 团队发布的测试中:

场景 旧 Blink LayoutNG
复杂嵌套 flex 明显卡顿 显著下降
大量 shrink 多次 layout 单轮
精度误差修正 多次回流 基本消除
复杂 writing-mode 很慢 稳定

典型提升:

20% ~ 40% 某些极端场景 > 2x


# 六、LayoutNG 的一个关键突破

它把 Layout 变成了:

“函数式布局系统”

Layout(node, constraint) → fragment
1

无副作用

这意味着:

  • 更容易并行化(未来)
  • 更容易缓存
  • 更容易调试

# 七、为什么现在 Flex 不再是性能黑洞?

因为:

  1. 单向约束流
  2. Fragment 缓存
  3. 精准 invalidation
  4. 避免多轮 shrink/grow
  5. 统一 intrinsic 计算

Flex 仍然比 block 重,

但已经:

从“不确定复杂度”变成“可预测复杂度”


# 八、你可以如何验证?

打开 Chrome DevTools:

Performance → Record

看:

  • Layout 时间
  • Layout invalidation
  • Forced reflow

你会发现:

现代 Chrome 中 Flex 的 layout 次数明显少于 2018 年以前版本。


# 九、终极总结

旧版 Blink Flex:

状态驱动 + 双向传播 + 多轮测量

LayoutNG Flex:

约束驱动 + 单向数据流 + 函数式输出

这是一次架构级优化。

上次更新: 2026/02/25, 10:02:17
shadcn/ui radix ui 讲解
min-content 仍然是 Flex和Grid 最大的性能风险

← shadcn/ui radix ui 讲解 min-content 仍然是 Flex和Grid 最大的性能风险→

Copyright © 2015-2026 Glitz Ma
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式