Now vibe coding, so learning hammer FE ?
《设计系统应该默认就是快的》

标签:
#前端开发 #设计系统性能优化 #性能测试 #性能预算 #WebComponents #组件渲染优化

总结:
这篇文章通过实测十大主流开源设计系统(Mantine、Ant Design、Material UI、React Spectrum、Carbon、Fluent、Web Awesome、UI5、Spectrum Web Components、Ionic),论证了性能应当与设计系统团队所重视的可达性(accessibility)平起平坐:底层组件的每一个性能修复,都会同时惠及所有基于该设计系统构建的应用。测试发现性能优劣并不取决于框架本身,而在于具体实现细节,作者还深入剖析了 Ionic、Ant Design、UI5、React Spectrum 等慢速组件的根因,并给出了可行的修复建议,最后提供了基于 Playwright 的自动化性能测试方案与「Fast by Default(默认即快)」的理念。

文章要点:
1. 浏览器的 JavaScript 主线程是所有层共用的,设计系统组件越慢,留给应用代码的余地就越小——修复一个设计系统组件的性能,等于同时提升所有依赖它的应用。
2. 作者选取了十个基于不同框架(React、Lit、FAST、Stencil、SAP 自研框架)的设计系统,在 4 倍 CPU 降速、Chrome 155 环境下实测了两大典型场景:打开含 249 个国家的下拉选择器、一次性全选 100 个复选框。
3. 实测结果差异巨大:国家选择器从最快 Fluent 的 61ms 到最慢 Ionic 的 1,266ms(比第二名慢 5 倍以上);复选框从 Fluent 的 29ms 到 Ant Design 的 421ms——同一框架(如 React 或 Lit)内部差距同样悬殊,性能问题出在实现而非框架。
4. 十个设计系统中只有 Spectrum Web Components 在每个 PR 上自动跑组件级性能基准,多数团队只检查包体积——但包体积与组件在页面上的响应速度并无直接关系。
5. 作者逐一剖析了慢速根因:Ionic 因 Stencil 在无 shadow DOM 的场景下用 appendChildSlotFix 模拟插槽、每次新增选项都要遍历全部既有子节点三次(O(n²));React Spectrum 因 React Aria 逐个清空高度再读取尺寸造成「布局抖动」;UI5 因隐藏弹层中预置全部 249 个选项,打开瞬间浏览器要一次性完成约 1500 个元素的样式计算;Ant Design 的慢则主要来自 100 个复选框同时触发的颜色渐变动画。
6. 性能瓶颈各有解法:长列表用虚拟滚动(Ant Design 的做法值得借鉴,还为屏幕阅读器保留了高亮项的隐藏副本);动画改由合成器线程运行的 opacity 渐变替代主线程上的颜色渐变;Stencil 可直接修复插槽回退内容的第三次检查,作者实测去掉后加 2000 个元素快约 7 倍。
7. 作者分享了用 Playwright + Chrome DevTools 协议(CPU 降速 4 倍 + Long Animation Frames 长帧 API)编写组件性能测试的完整代码,包含「总耗时预算 300ms」和「最长无响应帧不超过 100ms」两条性能预算(performance budget),以及一条「选项翻倍时耗时增长不超过 2.5 倍」的防 O(n²) 回归测试。
8. 落地的最佳实践是「默认就提供快的行为」:超过性能预算的列表自动切换虚拟化、复选框仅在被直接点击时才播放动画,并在文档中写明每个组件的测试数据规模上限,发布说明中给出修复前后的量化数据(如「500 个选项下打开从 300ms 降到 150ms」)。
9. 以上测试代码已开源在 GitHub 仓库 design-system-performance-tests 中,可直接复制改造用于自己的设计系统,并附带 GitHub Actions 工作流实现每个 PR 自动跑性能测试。
10. 文章结尾宣传了作者的新书《Fast by Default: Practical Performance Engineering》(Manning 早期访问版),把这套思路延伸到后端与移动端。

URL:https://denodell.com/blog/design-systems-should-be-fast-by-default Design Systems Should Be Fast by Default
《在 GitHub Copilot 应用中流畅渲染超大 Pull Request》

标签:
#软件工程 #前端性能优化 #PullRequest #虚拟化渲染 #React #测量调度 #滚动锚定 #性能监控

总结:
文章介绍了 GitHub Copilot 应用如何重构 Pull Request 视图,使其能够流畅处理包含 2,200 个文件、超过 100 万行代码变更和 400 多条内联评论的超大型 PR。核心挑战在于评论高度的动态性——与代码行不同,评论高度取决于 Markdown 换行、可展开区块、回复框和图片加载等渲染时才能确定的因素。团队通过分离确定性与动态几何、实现智能测量调度器、采用滚动锚定技术,并建立自动化测量循环来解决这一问题,最终实现了百万行 diff 的流畅浏览体验。

文章要点:

1. 代码与评论的几何分离:代码行高度固定且可预先计算,而评论高度动态变化。团队将文档高度分为确定性代码高度(精确前缀和)和动态块高度(估算后测量),两者独立管理,避免评论调整时重建整个代码几何。

2. 智能测量调度器:放弃每块一个 ResizeObserver 的方案(会触发反馈循环),改为单一的空闲和滚动门控测量通道。仅在视口附近约 2400px 范围内进行测量,屏幕上的块优先批量读取,离屏块最多做一次有限渲染,超过视口高度的块跳过测量。

3. 滚动锚定技术:当测量高度与估算不符时,通过身份而非像素来校正——记录用户锚定的行或块,应用高度增量后,将同一锚点解析到新像素位置并滚动,确保用户视线不跳动。区分用户滚动与程序滚动,避免侧边栏切换等操作误触发保护机制。

4. 数据管道优化:流式传输结构优先于内容,文件树和元数据在文档加载时即可渲染;语法高亮在主线程外运行,行先以纯文本显示;释放文档时保留最近几个 diff 的缓存,平衡内存与返回时的加载速度。

5. 自动化测量循环:建立"变更→测量→改进"的无人值守循环,包括无头探针车道(声明式流程 + 生产环境插桩)和自动驾驶仪(驱动真实桌面应用),通过健康信号(如无未填充间隙、评论块非空)自动检测问题,实现机械式调试而非人工复现。

URL:
https://github.blog/engineering/user-experience/rendering-huge-pull-requests-in-the-github-copilot-app/ Rendering huge pull requests in the GitHub Copilot app
《浏览器主线程很昂贵:高性能前端优化实战指南》

标签:
#前端 #Web性能 #浏览器原理 #JavaScript #渲染管线 #WebWorker #动画优化 #交互优化 #性能调优

总结:

本文深入剖析了浏览器主线程作为稀缺资源的工作原理,指出前端性能问题的根源往往不是代码速度慢,而是主线程被长时间占用导致界面冻结。文章系统性地介绍了两大类优化策略:在主线程上"精打细算"(拆分、批处理、优先级排序、延迟执行),以及"完全不用主线程"(利用合成器线程、Web Worker、消除不必要的工作),并通过大量交互式 Demo 帮助读者直观理解每种技术的实际效果。

文章要点:

1. 主线程是性能瓶颈的核心:主线程同时负责运行 JavaScript、样式计算、布局、绘制和事件处理,所有工作排队串行执行。60Hz 屏幕每帧预算约 16.6ms,实际可用仅约 10ms,超过 50ms 的任务会导致界面卡顿。

2. 拆分(Splitting):将大任务切割成小片段,通过 setTimeout 或 requestAnimationFrame 让出主线程,让浏览器在间隙处理渲染和输入。注意过度拆分会产生额外开销,且 JSON.parse 等原子操作无法拆分。

3. 批处理(Batching):将频繁触发的事件(如滚动、输入)合并执行,使用防抖(debounce)和节流(throttle)减少重复劳动。React 的虚拟 DOM 本质上也是一种批处理机制。

4. 优先级排序(Prioritizing):通过自定义队列(基于 MessageChannel)实现任务插队机制,确保用户当前关注的操作(如点击预览图片)优先执行,采用"空闲时预处理,紧急时优先处理"的策略。

5. 延迟执行(Deferring):非必要工作延后处理,包括代码分割、使用 IntersectionObserver 实现虚拟列表(只渲染可视区域内容)、离屏时暂停动画等,避免一次性处理全部数据。

6. 利用合成器线程:使用 transform 和 opacity 代替 top、left、width 等触发布局的属性做动画,让动画在合成器线程运行,即使主线程繁忙也能保持流畅。

7. FLIP 动画技术:对于必须改变布局的动画(如列表重排),先测量初始和最终位置,通过反转和播放 transform 来实现平滑过渡,将布局计算限制为仅一次,动画过程交给合成器。

8. Web Worker 处理重计算:将图片处理、大数据解析等纯计算任务转移到 Worker 线程,通过 postMessage 的 Transferable 对象(如 ArrayBuffer)实现零拷贝数据传输,避免主线程冻结。

9. 消除不必要的工作:当数据流入速度超过处理能力时,采用丢弃(旧日志)、合并(只保留最新值)、跳过(缓存 memoization)三种策略,从源头减少工作量。

10. 避免布局抖动(Layout Thrashing):不要交替读写布局属性(如 offsetWidth),应先批量读取再批量写入,强制浏览器反复计算布局会严重阻塞主线程。

URL:
https://kciter.so/posts/the-expensive-main-thread/en/ The Browser's Main Thread Is Expensive | kciter.so
《关于协作编辑的谎言(第二部分):为什么我们不用Yjs》

标签:#前端 #ProseMirror #CRDT #协作编辑 #性能优化 #Yjs #实时协作

总结:
本文是Moment.dev团队关于协作编辑算法分析的第二部分,作者详细阐述了为何在生产环境中放弃Yjs而选择基于ProseMirror-collab的简单方案。文章指出Yjs存在严重的性能问题(每次协作编辑会销毁重建整个文档)、与文档Schema冲突、权限控制困难、调试困难以及墓碑数据占用内存等问题。作者认为,除非真正需要无主节点的P2P架构,否则40行代码的"简单方案"在性能、可维护性和开发体验上都优于复杂的CRDT实现。

文章要点:
- Yjs存在严重性能缺陷:每次协作编辑会销毁并重建整个文档,导致60fps目标难以达成,影响NodeView、插件状态、撤销功能和光标位置管理
- 简单方案仅需40行代码:使用prosemirror-collab库,通过单一权威节点管理文档版本和事务,支持乐观更新、离线编辑和网络中断恢复
- Yjs与文档Schema冲突:在无主节点架构下难以验证事务有效性,可能导致数据永久丢失,升级时尤其危险
- 权限控制复杂化:需要将Yjs的XML更新预测转换为ProseMirror事务来判断权限,实现难度大
- 墓碑数据问题:Yjs需保留删除标记,导致内存持续增长或数据丢失风险,而简单方案通过数据库存储步骤即可解决
- 调试困难:CRDT仅保证最终一致性,难以区分暂时分歧与真正错误,调试工具受限
- 核心观点:技术选型应从最终用户体验出发,而非算法本身;如无P2P刚需,简单方案在各方面均优于CRDT

文章URL:https://www.moment.dev/blog/lies-i-was-told-pt-2 Lies I was Told About Collaborative Editing, Part 2: Why we don't use Yjs / Moment devlog
《理解 React Fiber 存在的意义》

标签:#前端 #React #React_Fiber #性能优化 #并发渲染 #Virtual_DOM

总结(一段话概括)
React Fiber 是 React 16 对核心协调算法的彻底重写,旨在解决 React 15 中 Stack Reconciler 同步递归更新导致的主线程阻塞问题。通过将组件树重构为链表结构的 Fiber 节点,React 实现了可中断的异步更新、任务优先级调度和时间切片机制,使高优先级任务(如用户输入)能插队执行,避免页面卡顿,并为 Concurrent Mode、Suspense 等现代特性奠定基础。

文章要点:
- React 15 的瓶颈:Stack Reconciler 采用递归遍历,更新一旦开始无法中断,复杂组件树会导致主线程长时间阻塞,造成掉帧和交互卡顿
- Fiber 的本质:将同步更新改为可中断的异步更新,每个 Fiber 节点是一个执行单元,通过 child、sibling、return 指针形成链表树,取代递归调用栈
- 时间切片(Time Slicing):利用 requestIdleCallback polyfill(基于 MessageChannel),在浏览器每帧(16.6ms)中预留时间(默认 5ms)给 React,超时即让出主线程控制权
- 优先级调度:引入 Lanes 机制,区分 Immediate(最高)、UserBlocking、Normal、Low、Idle 五级优先级,确保紧急更新优先处理
- 双缓冲机制:维护 current Fiber 和 workInProgress Fiber 两棵树,通过 alternate 指针关联,渲染完成后直接切换指针指向,避免重复创建对象
- Phase 分离:将更新分为 Render 阶段(可中断,构建 Fiber 树)和 Commit 阶段(不可中断,同步执行 DOM 操作),支持错误边界(Error Boundaries)捕获
- 架构演进:从 React 15 的两层(Reconciler + Renderer)增至 React 16+ 的三层(Scheduler + Reconciler + Renderer),调度器负责任务分配和中断控制

文章URL:https://inside-react.vercel.app/blog/understanding-why-react-fiber-exists Understanding Why React Fiber Exists
 
 
Back to Top