Wilson Page 为 Smashing Magazine 撰写了一篇 非常棒的文章,深入探讨了一个真实网站及其团队用来构建它的所有酷炫的现代工具和技术。
对于布局,他们最初选择了 flexbox,但是……
随着应用程序的不断发展,我们发现性能变得越来越差。
我们在 Chrome 开发者工具的时间轴上花费了几个小时,并找到了罪魁祸首:令人震惊!——正是我们新的最佳朋友 flexbox。时间轴显示某些布局花费了近 100 毫秒;在没有 flexbox 的情况下重新设计我们的布局将此减少到 10 毫秒!
在 文章中有一些开发人员工具时间轴的对比截图。令人担忧,不是吗?
我正在与 Tim Kadlec 讨论此事。Tim 说他联系了团队,看看他们是否创建了简化的测试用例或是否有更多数据可以分享。不幸的是,他们没有。
也许我们可以找到这些数据。我构建了一个小的随机 flexbox 布局生成器。
查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 生成大量 Flexbox
滑动范围滑块即可重新生成随机 flexbox 布局。越向右,越多。到目前为止,我还没有发现任何特别费力的东西。但是,我在这里的小演示并不完全是“现实世界”。也许里面的图片有问题。也许使用 flexbox 属性 更改源顺序是费力的原因。也许 旧的 flexbox 是罪魁祸首。也许根本没什么好担心的。
如果您有任何关于如何复制 flexbox 周围的一些不良性能的想法,请随时分叉我的生成器,并添加/更改使之发生所需的内容。
我所知道的实际衡量性能的最佳方法是 Chrome 开发者工具 > 时间轴。然后点击“录制”按钮,滑动滑块,然后停止。然后在时间轴上查找较长的绘制时间。像这样

那里的紫色是布局,在这种情况下(到目前为止)很快。
我将更新此帖子
如果我们能够收集一些可靠的数据,我将使用最接近答案的内容更新此帖子,以回答这篇博文标题的问题。
更新:以及 这里我们来啦!
我在构建应用程序时也遇到了同样的问题。
除了整体布局外,使用 flexbox 的视图是一个带有月份视图的日历。将其显示在屏幕上会使渲染速度大大降低。
切换到日历视图的表格,使整个视图的速度提高了十倍。
很有意思!您是否为此创建了比较测试用例?这正是这里需要的。
度假回来后,我就可以尝试重现它了 :-)
但是,表格始终比自由样式的标记更具性能——使用浮动系统重新创建表格布局(正如许多标准化时尚人士热衷于做的那样)会对渲染速度产生巨大影响。
@Barney .. 没有数据很难说。我对差异数据很感兴趣。
Jeppe,您是否在 Opera 上尝试过,我的浏览器开始挂起?
我试图重现我的问题,但我没有看到大的性能问题。
我之前使用过 angular,这次没有。
http://codepen.io/bobslaede/full/pixcn
查看一下。
@Ajman
我还没有在 Opera 中尝试过
为什么我认为这可能不是“flexbox”的错,而是浏览器实现的错……
我认为“旧”flexbox 很可能是比新 flexbox 更大的罪魁祸首,希望有一些数据可以证明这一点。
我可以确认我们遇到的性能问题与旧的
display: -webkit-box;
语法有关。我们还在 Blackberry Playbook 上通过从 The Economist 网页应用中删除不必要的 flexbox 获得了巨大的布局性能提升。我不能说明新语法在移动设备上的性能,因为它目前在任何目标设备上都不受支持。非常好,很高兴知道。
您是否准备了一些测试用例?我的目标是提供一个我们可以向人们指出的演示,并说,看,这就是问题所在。真实的演示/真实数据之类的东西。
我想再多玩玩这个……在上面的演示中,很难将布局成本与绘制、innerHTML(将 HTML 解析为 DOM 非常耗时!)和下划线模板进行比较。
所以我对旧语法和新语法进行了面对面的比较,因为我知道 FT 团队使用了旧的 flexbox 而没有使用面向未来的语法。
旧版和新版 Flexbox 基准测试
新版 flexbox:布局成本约为 _18.2 毫秒_
旧版 flexbox:布局成本约为 _43.5 毫秒_**
因此,旧版比新版慢 2.3 倍。
总结
使用 flexbox 时,始终针对新内容编写代码,以及 IE10 过渡语法以及 Chrome 21+、Safari 6.1+、Firefox 22+、Opera(和 Opera Mobile)12.1+、IE 11+ 和 Blackberry 10+ 中的新 更新的 flexbox。
(我对这个演示的布局成本使用
float
或display:table
有点好奇,但是……这些数字将非常特定于这种特定的布局样式。)更重要的是优化重要的事情。在花费时间优化某种操作之前,始终使用时间轴来识别您的瓶颈。FT 确实在其代码中遇到了布局瓶颈,但我一直在与 Wilson 合作解决这个问题,并且我们将因此改进 Chrome 开发者工具!
人人受益。
太棒了,Paul!感谢您澄清这一点 :)
我们现在确实使用了未来的语法,但任何性能提升都不会在移动版 Safari(我们的主要平台)上生效,直到 iOS7 发布。我还认为它将位于“ -webkit-”前缀之后,与 Chrome(当前为 Canary)不同,您可以在其中以其所有未加前缀的辉煌使用它 :)
为了好玩,Chris 和我刚刚尝试了 display:table-cell,它达到了 30 毫秒,正好在这两者之间。非常棒。
我应该指出,这些数字特定于 Webkit/Blink。由于实现时间,flexbox 在 Safari 和 Chrome 以及 Android 上几乎相同。
谁在乎它是否慢?你要怎么做?再次使用浮动和奇怪的伪列?不,我选择 18 或 45 毫秒。
好吧。45 毫秒不是很多,但在移动设备上乘以 10 就是 450 毫秒,您需要等待半秒才能完成通常接近于零的事情,并且没有考虑所有其他传统的速度罪魁祸首。这在一个相当极端的布局上,但仍然需要注意。
就我而言,我宁愿努力使用旧的布局方法,也不愿让整个页面对移动用户造成半秒的延迟。
在连接糟糕的小型设备上,性能才是最重要的。无论编码容易还是困难。
我有点同意 Hugo 的观点。根据项目的规模,性能问题可能会导致我完全放弃使用 Flexbox 进行布局。我考虑过在现有的网格框架中使用 Flexbox 来构建组件;在它效果不佳的地方回退。我将继续进行自己的实验,看看这种方法的可维护性如何。
关于移动端速度慢10倍的事情……有多少网站在移动端和桌面端使用相同的布局?我相信,为移动端去除大部分(如果不是全部)flexbox的东西应该很容易。
CrocoDillon
@CrocoDillon 你说得对,Flexbox对于小尺寸手机屏幕来说并不那么有用,但在较大的平板电脑尺寸的移动设备上,它是有用的。
移动端的flexbox布局很简单,盒子通常少于10个。即使有速度下降,也是可以忽略不计的。我们的移动端框架是围绕flexbox构建的,这似乎并没有减慢它的速度。
谢谢你们!我刚刚掌握了flexbox,并开始在我的项目中使用它,当我读到Wilson Page的文章时,我真的很希望有人能更深入地研究那个说法。你读懂了我的想法。Chris和Paul,超级粉丝!
我也有类似的问题。我们有一个旧规范的实现,最新版本的Firefox最终会在脚本上超时(我认为是DOM插入)。我更新了代码以包含新规范,它可以工作了,但速度非常慢。
对我来说,问题在于嵌套过多。它在一个带有div-itis的CMS中,所以我不得不对许多嵌套元素应用flex: 1。我覆盖了默认模板以减少标记,现在运行非常流畅。但我目前还没有任何数据可以提供。
flexbox模型已经在生产环境中使用了吗?我以为在实际的网站中使用flexbox还很遥远?
@kaspar,我们很幸运,只需要支持iOS、Android、Windows 8(IE10)和Firefox。所有这些都至少支持
display: box;
规范。如果你需要支持IE 7、8或9,则需要优雅降级,或找到替代方案。我相信也有一些JavaScript polyfill可以填补Flexbox的空白。不。许多客户仍然希望对IE8或IE9进行优化。当然,这很痛苦。
使用flexbox会对布局产生一般性的影响。它不像不支持的阴影那样。
也许我跑题了,但这里有一个在生产环境中使用flexbox的网站ocomcareers.com
无法说明它慢了多少,我只能说它在移动端也不是那么糟糕。
由于我没有在其他地方看到相关文档,所以我花时间将所有flexbox属性收集在一起,并链接到它们的参考文档。任何与不同实现相关的内容,包括Apple、Microsoft、Mozilla或W3C网站上的内容,都按你想要使用的顺序列出(因此Chrome中较新的flexbox实现会覆盖较旧的实现),所有内容都放在一个地方:Flexbox / Flexible Box Layout CSS 参考。
当我要为IE8优化网站时,我在Smashing Magazine上看到了这篇文章。气死我了。
希望浏览器厂商现在能开始优化它,因为他们将开始获得大量的真实世界反馈和示例。
我觉得我在这里得到了不同的结果!……有人在Opera版本上尝试过吗?
根据我的经验和测试,flexbox在Firefox中遇到了特别的问题——我认为明智的做法是测试它以及Chrome——我们甚至看到非常简单的布局在FF中加载速度慢了20到30倍(这让我们非常震惊)。
但是我认为我们的大多数测试都是使用旧语法运行的,旧语法看起来慢得多。
在开发https://play.google.com/store/apps/details?id=com.triapodi.apprec时,我只是通过移除
flexbox
(Webkit过时的flexbox语法)和border-radius
,就将性能提高了至少6倍。你是否有相关的测试/数据?这太棒了,正是我想在这篇文章中收集的内容。我担心人们会看到诸如“不使用flexbox速度快了六倍!”这样的说法,但没有上下文或数据来解释这意味着什么以及具体测试了什么。这尤其有趣,因为在移动端,旧语法最普遍,而且几乎肯定速度较慢,因此如果我们能收集到真实的数据,那将是令人惊叹的。(我不确定如何在移动端获得真实的性能分析数据)。
我认为这只是突显了一个事实,即在现实世界中,我们可能只需要克制自己不去使用一些较新的技术,即使用户群拥有支持该技术的浏览器……但这主要突显了一点,即测试我们作为开发人员所产出的任何内容都是关键。
我们一直在使用jQuery Mobile 1.3.2和Knockout.js的SASS版本构建一个网站。由于jQuery Mobile中的网格功能有限,并且我们需要在列方面有很大的灵活性,以便能够在各种尺寸的屏幕上显示内容,所以我尝试将基于flexbox的网格引入解决方案中。我最终使用了flexgrid,因为它有对旧flexbox的回退,并且已经准备好了SASS组件。
在引入flexbox之前,我们已经遇到了一些问题,即在视图中加载数百个项目的列表——我希望flexbox能够解决速度和响应性问题,帮助框架更快、更流畅地完成任务。
在台式机/笔记本电脑上获取应用程序并下载数据的实际时间还可以,符合预期。但是,当我们使用Windows 8平板电脑(配备Atom处理器)和IE10(将用于使用该应用程序)时,时间就变得非常糟糕了。
在使用flexbox之前,我们从服务器检索大约450个项目的列表需要大约1分钟10秒。使用flexbox后,时间延长到大约1分钟40秒。当我使用Chrome时间轴调查症状时,它显示数据解析、渲染和检索占据了大部分时间。
我决定放弃flexbox,并找到一种方法来使用jQuery Mobile网格获得更快的结果——我只是没有时间进一步测试它。
我从中学到,flexbox还不是构建大型数据集列表的方法——至少现在还不是。它可能适用于较小的静态网站或页面,但不适用于数据密集型页面。
在切换回jQuery Mobile网格系统后,我将IE10上的下载时间缩短到40秒,Chrome上的下载时间缩短到20秒,同时我还删除了jQuery Mobile列表视图JavaScript。但是,Chrome似乎无法像IE那样渲染列表,并且会生成重影……
我的移动UI框架的布局管理器完全基于flexbox模型(旧语法和新语法)。我还没有在任何我测试过的移动设备上看到任何明显的性能下降。当然,速度在这些设备的处理能力方面是相对的,但测试没有表明任何需要警惕的事情。请注意,在任何一个屏幕/页面上,我们都在20-80毫秒内布局/渲染大约500个元素。我认为其他已知的“缓慢”CSS属性(box-shadow、border-radius、渐变……)可能是某些性能问题的罪魁祸首。
无论如何,我只是想发表一下我的看法。
只想提一下,我们观察到性能随着嵌套flexbox数量的增加呈指数级下降。我不确定这是否已纳入任何性能测试。
Wilson,你说的很有道理。在我的UI框架中,所有容器本质上都是flexbox,但它们的子元素不一定都是flexbox/flex-item。也就是说,在我编写的示例应用程序中,flexbox的最大嵌套级别为4(每个元素),所以我不知道这是否能很好地代表你的测试或你所看到的情况。
需要用“x”个嵌套flexbox进行自己的测试,以查看性能何时开始明显下降。
顺便说一句,跑题了,我非常喜欢你的FastDom……:)
谢谢Cesidio!希望它能对加快移动网页速度发挥一点作用:)
Flexbox确实存在性能问题,但问题不在于Flexbox本身,而在于其实现。
首先,新的Flexbox可能比旧的快,但毫无疑问,Mozilla旧的Flexbox实现比Webkit的新实现要快。
证明这一点的是,我们能够在没有任何延迟的情况下调整XUL GUI的大小;相反,现在在Chrome上调整具有类似内容的GUI会导致2-3秒的整页渲染。
但最糟糕的是优化方面。
除非你要修改一个固定大小的矩形,否则每次DOM修改都会导致整页渲染,这会导致整个浏览器窗口冻结至少几秒钟。
我无法评价Mozilla的新实现,因为我发现了一个导致浏览器崩溃的bug,我还没有时间检查导致它的原因。
如果有人感兴趣,我会设置一个演示来展示这些问题。
(注意:我进行的每个测试都没有使用渐变、阴影、圆角、不透明度或可能导致性能问题的其他设置)
例如,
这两个代码片段产生的结果基本相同,但在实践中,修改#test1的DOM子树会导致整个文档重新渲染,而#test2只会重新渲染元素本身及其部分子树。
(注意:我实际上并没有单独测试这段代码,只是说这种情况在我的实际GUI中发生了)
希望在假期期间能找到一些空闲时间来设置一个测试页面。
抱歉,我的思维还在使用
-moz-box-orient
:Pflex-direction:vertical
=>flex-direction:column
Wes,一个测试页面和一个crbug.com上的工单将非常棒。我们希望确保实现速度很快,因此您的测试用例将非常有助于我们进行优化。非常感谢!
如果您需要任何帮助,请随时告诉我。
感谢您的反馈!根据我的经验,在bug跟踪器上提供大量代码并不能帮助修复bug :P
我应该尝试隔离问题吗?我相信其中涉及许多问题,肯定不是全部都与Flexbox相关,并且可能每个问题都应该有自己的bug报告。
是的,请!那将非常完美。 crbug.com 是 Chrome 的错误报告地址。 coding.smashingmagazine.com/2011/09/07/help-the-community-report-browser-bugs/ 包含所有详细信息。
已提交第一个报告! 331352
希望它足够详细和“隔离” :P
谢谢
无论如何,伙计们,我想我对Flexbox进行了不好的宣传,所以我想也说一下这一点。
试一试,给浏览器一些时间。
毫无疑问,Flexbox非常棒。
我一直在使用Flexbox开发一个网络应用程序,并且一切都很顺利,持续了相当长一段时间。但过了一段时间,我发现我的网络应用程序在Firefox中变得非常非常慢,而Chrome和IE能够毫无问题地处理它。我以为问题可能与Flexbox有关,所以我在谷歌上搜索并找到了这篇文章,并测试了上面的示例。但是,将许多Flexbox并排放置似乎并没有损害我测试的任何浏览器。
然后我稍微修改了一下示例,以便递归地将Flexbox添加到彼此内部。
JSFiddle
问题出现了:Chrome在处理40个或更多嵌套的Flexbox时没有任何问题。但是,如果让Firefox绘制10个嵌套的盒子,它就会冻结一段时间…
有没有人对此问题有好的解决方案?:/
我也是…
在Firefox中无法使用嵌套的Flexbox。
http://codepen.io/anon/pen/dhzJE(限制为20个项目,否则您需要终止Firefox进程)