2

Even though my DOMContentLoaded event is fired at ~500ms, the first paint happens around 3.5s due to a very long layout phase.

enter image description here

Can anyone advise me as to why this might be happening, and how I can fix it? Currently the page does have ~350 nodes, but I've seen other sites with similar nodes and a 50-100ms layout phase.

enter image description here

What am I doing wrong?

P.S. This is a universal React app and I'm using Heroku Standard 1x and Fastly CDN to serve it.

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
Seungchan Lee
  • 111
  • 2
  • 3
  • 4
  • It needs to be replicable with an actual code example if you'd like people to diagnose the issue. – Emissary Mar 29 '16 at 08:10
  • I'm new to SO - I'm not certain how I can include relevant code here given the nature of the problem. I can point to the site https://zensacream.com so you can take a look at the html. What else would you need to diagnose this? – Seungchan Lee Mar 29 '16 at 14:29

1 Answers1

2

Use the following steps to minimize the number of nodes that need layout:

  • Use relatively positioned containers with absolutely positioned children to handle bookend and centering layout needs:

Absolutely positioned elements are removed entirely from the document flow. That means they have no effect at all on their parent element or on the elements that occur after them in the source code. An absolutely positioned element will therefore overlap other content unless you take action to prevent it. Sometimes, of course, this overlap is exactly what you desire, but you should be aware of it, to make sure you are getting the layout you want!

  • Avoid animation based on the positioning of an element:

The handler computes each image's left property based off of the image's offsetTop value. This forces the browser to perform a new layout immediately to make sure that it provides the correct value. Forcing a layout during every animation frame is the cause of the janky animations on the page.

  • Avoid calculations that depend on computed values of DOM elements:

As a general rule of thumb, if you ask for a geometric value back from the DOM before a frame is complete, you are going to find yourself with "forced synchronous layouts", which can be a big performance bottleneck if repeated frequently or performed for a large DOM tree.

  • Replace float with inline-block if possible:

Any content in the current line before a floated box is reflowed in the first available line on the other side of the float.

  • Use display: flex instead of display: table or JavaScript based layout if possible:

The new flexbox code has a lot fewer multi-pass layout codepaths. You can still hit multi-pass codepaths pretty easily though (e.g. flex-align: stretch is often 2-pass). In general, it should be much faster in the common case, but you can construct a case where it's equally as slow. That said, if you can get away with it, regular block layout (non-float), will usually be as fast or faster than new flexbox since it's always single-pass. But new flexbox should be faster than using tables or writing custom JS-base layout code.

  • Only use bottom as a value for the vertical-align property:

The inline boxes are aligned vertically according to the 'vertical-align' property value for source inline elements. If an element has the values 'top' or 'bottom' for this property, only the height of the generated boxes affects the line box height calculation; the boxes cannot be aligned until the line box has been fully constructed. Note that if all the boxes in the line box are aligned along their bottoms, the line box will be exactly the height of the tallest box. If, however, the boxes are aligned along a common baseline, the line box top and bottom may not touch the top and bottom of the tallest box.

  • Use inline-block with a fixed height for numerous inline elements that need to be vertically positioned:

The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.

  • Use shouldComponentUpdate to optimize rendering:

In practice, anything complicated probably requires shouldComponentUpdate for acceptable performance. Writing reasonably efficient shouldComponentUpdate in turn requires underlying data that can be compared quickly, hence for example the current interest in immutable data structures that can be tested for equality by checking a single reference. And so the choice to use React for rendering does have implications for how the underlying data is stored as well, which undermines any claims about truly separating the view logic from the business logic.

References

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265