PRPL on Rails Part 2: Optimize Rendering
This is the second of a three-part series on speeding up your Rails application using techniques from the PRPL pattern.
In our previous post, we talked about improving your page load time by splitting your into code bundles and loading only what's needed for a particular route. Your performance enhancements don't have to end there. Once your code has arrived at the browser, you will want it to render as quickly as possible so that your user can start interacting with the page right away. The "R" in PRPL stands for "Render" and this post will show you how to improve your rendering speed.
There is a lot you can do to optimize rendering, so much that it can be overwhelming. We recommend that you begin by determining what's slowing your site down. Measuring your performance can help you target the big problems and avoid spending too much time on improvements that are not going to have much effect on your rendering speed.
A great first step is to run your site through a Lighthouse audit. Lighthouse will assess your site's performance and give you a list of actions that you can take to make your site faster. The easiest way to access Lighthouse is through the Chrome developer tools. Open the dev tools and click on the "Audits" tab. Click on the "Perform an audit…" button and then select "Performance" on the list of audits you can perform. After a few seconds, Lighthouse will present a report that includes your time to first meaningful paint, your time to interactive, and other useful information, as well as a list of "Opportunities" for increasing your app's speed.
Critical Rendering Path
To make sense of the loading timeline and improve your loading performance, it is helpful to understand how the browser turns your code into the web page that your user sees. This process is called the critical rendering path.
Next, the bowser constructs the CSSOM (CSS object model), which like the DOM is a a tree structure made of nodes. This phase can also take time. It is represented in the dev tools as a "Recalculate Style" event. Once the DOM and CSSOM trees are constructed, the browser combines them into a "render tree." The render tree contains only elements that are visible–no meta tags, no elements styled with
display:none. Next, the browser positions the render tree in the viewport. This is phase is sometime called "layout" or "reflow". Finally, the browser paints the pixels on the screen.
Small, Lazy, and Flat
Favor fewer elements and less complexity. Keep the size of your DOM as small as possible. Avoid deeply nested elements, which can take a long time to render. (In the exercise below, you will measure the cost of nested HTML.)
Keep critical CSS small. On your initial load, don't ship any more CSS than you need. You can reduce the size of your CSS by using media types and queries. These can prevent you from loading print styles that don't apply to your user's device or situation.
<link rel="stylesheet" media="print" href="print-styles.css" /> <link rel="stylesheet" media="screen and (min-width: 700px) and (max-width: 900px)" href="medium-width-styles.css" />
You might also be able to reduce the size of your CSS by removing any styles that aren't being used. The coverage panel in Chrome dev tells can help you identify unused CSS and JS. If your CSS file is still large, try limiting your critical CSS to styles that apply above the fold and lazy load additional page styles.
Enjoy! And don't hesitate to share your thoughts or questions with us.
- Building the DOM faster: speculative parsing, async, defer and preload
- Critical Rendering Path, by Ilya Grigorik, Google Web Fundamentals
- Measuring Websites With Mobile-First Optimization Tools
- Rendering Performance, by Paul Lewis, Google Web Fundamentals
- Tips for authoring fast-loading HTML pages, MDN Web Docs
- Web Font Optimization, by Ilya Grigorik, Google Web Fundamentals
- Website Performance Optimization, Udacity Course
- What Forces Layout, Paul Irish