{"id":1489,"date":"2020-09-04T11:18:01","date_gmt":"2020-09-04T11:18:01","guid":{"rendered":"https:\/\/lvboard.infostore.in.ua\/?p=1489"},"modified":"2020-09-04T11:18:01","modified_gmt":"2020-09-04T11:18:01","slug":"how-to-improve-page-speed-from-start-to-finish","status":"publish","type":"post","link":"https:\/\/lvboard.infostore.in.ua\/?p=1489","title":{"rendered":"How to Improve Page Speed from Start to Finish"},"content":{"rendered":"\n<p>There are lots of tools to test page speed, and lots of different metrics to target. But do you understand how those optimizations work, or whether they\u2019re actually going to make your website faster?<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Page speed is a complex topic. Many of the existing articles give you a list of actions to take or plugins to install to help with different aspects of speed. That\u2019s fine, but not all sites are the same. So, in this post, I\u2019ll help you understand how page speed works, and what actions to take for your particular site.<\/p>\n\n\n\n<p>With that said, if you are not technical and you\u2019re just hoping to install a plugin\/module to speed up your site, here are some that should help:<\/p>\n\n\n\n<p><strong>WordPress:<\/strong><\/p>\n\n\n\n<ul><li><a href=\"https:\/\/wp-rocket.me\/\" target=\"_blank\" rel=\"noreferrer noopener\">WP Rocket (paid)<\/a>&nbsp;+ an&nbsp;<a href=\"https:\/\/wordpress.org\/plugins\/search\/image+optimization\/\" target=\"_blank\" rel=\"noreferrer noopener\">image optimization plugin<\/a>, or:<\/li><li><a href=\"https:\/\/wordpress.org\/plugins\/autoptimize\/\" target=\"_blank\" rel=\"noreferrer noopener\">Autoptimize<\/a>&nbsp;+ a&nbsp;<a href=\"https:\/\/wordpress.org\/plugins\/search\/cache\/\" target=\"_blank\" rel=\"noreferrer noopener\">cache plugin<\/a><\/li><\/ul>\n\n\n\n<p><strong>Drupal<\/strong><\/p>\n\n\n\n<ul><li><a href=\"https:\/\/www.drupal.org\/project\/advagg\" target=\"_blank\" rel=\"noreferrer noopener\">AdvAgg<\/a>&nbsp;+ an&nbsp;<a href=\"https:\/\/www.google.com\/search?q=drupal+image+optimization+module&amp;rlz=1C1CHBF_enUS870US872&amp;oq=drupal+image+optimization+module&amp;aqs=chrome..69i57j0l2.8567j0j4&amp;sourceid=chrome&amp;ie=UTF-8\" target=\"_blank\" rel=\"noreferrer noopener\">image optimization module<\/a><\/li><\/ul>\n\n\n\n<p>Now, back to business. Here\u2019s everything I\u2019m going to cover:<\/p>\n\n\n\n<ul><li><a href=\"https:\/\/ahrefs.com\/blog\/advanced-pagespeed-guide\/#what-is-page-speed\">What is Page Speed?<\/a><\/li><li><a href=\"https:\/\/ahrefs.com\/blog\/advanced-pagespeed-guide\/#why-page-speed-matters\">Why You Should Care About Page Speed<\/a><\/li><li><a href=\"https:\/\/ahrefs.com\/blog\/advanced-pagespeed-guide\/#how-fast-should-my-page-load\">How Fast Should My Page Load?<\/a><\/li><li><a href=\"https:\/\/ahrefs.com\/blog\/advanced-pagespeed-guide\/#how-a-page-is-built\">How A Page Is Built<\/a><\/li><li><a href=\"https:\/\/ahrefs.com\/blog\/advanced-pagespeed-guide\/#page-speed-testing-and-tools\">Page Speed Testing And Tools<\/a><\/li><li><a href=\"https:\/\/ahrefs.com\/blog\/advanced-pagespeed-guide\/#estimating-impact\">Estimating Impact of Changes<\/a><\/li><\/ul>\n\n\n\n<p><a><\/a><\/p>\n\n\n\n<h2>What is Page Speed?<\/h2>\n\n\n\n<p>Page speed is the amount of time it takes for a web page to load. It is difficult to assign a single number to page speed because many metrics capture elements of the page load in different ways, for different purposes, and with different test conditions.<a><\/a><\/p>\n\n\n\n<h2>Why You Should Care About Page Speed<\/h2>\n\n\n\n<p>There\u2019s been a renewed focus on page speed from Google recently with&nbsp;<a href=\"https:\/\/webmasters.googleblog.com\/2018\/01\/using-page-speed-in-mobile-search.html\" target=\"_blank\" rel=\"noreferrer noopener\">mobile speed becoming a ranking factor<\/a>, a&nbsp;<a href=\"https:\/\/webmasters.googleblog.com\/2019\/11\/search-console-speed-report.html\" target=\"_blank\" rel=\"noreferrer noopener\">Speed Report<\/a>&nbsp;in Google Search Console, and&nbsp;<a href=\"https:\/\/blog.chromium.org\/2019\/11\/moving-towards-faster-web.html\" target=\"_blank\" rel=\"noreferrer noopener\">Chrome announcing they may flag sites that are slow<\/a>, but did you know that&nbsp;<a href=\"https:\/\/webmasters.googleblog.com\/2010\/04\/using-site-speed-in-web-search-ranking.html\" target=\"_blank\" rel=\"noreferrer noopener\">page speed has been a ranking factor for Google since 2010<\/a>?<\/p>\n\n\n\n<p>Here are the reasons you should care:<\/p>\n\n\n\n<ul><li><strong>Impacts User Experience<\/strong>. You want visitors to have a fast and smooth experience. Any delay or lag on their actions is noticeable.<\/li><li><strong>Impacts Analytics<\/strong>. Generally speaking, a faster site will record more visitors because the analytics tag will load sooner. If a person leaves before the tag is fired, they won\u2019t be recorded in the analytics system.<\/li><li><strong>SEO<\/strong>? The Speed Update only impacts the slowest sites according to the&nbsp;<a href=\"https:\/\/webmasters.googleblog.com\/2018\/01\/using-page-speed-in-mobile-search.html\" target=\"_blank\" rel=\"noreferrer noopener\">official announcement<\/a>.<\/li><\/ul>\n\n\n\n<p>There are lots of studies showing that if you increase page speed, you\u2019ll see increases in things like organic traffic, click to visit ratio on ads, more visitors in general, and many other benefits.&nbsp;<a href=\"https:\/\/wpostats.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">WPO&nbsp;Stats<\/a>&nbsp;has many example studies on page speed improvements.<\/p>\n\n\n\n<p>However, I will caution that many of these studies may be a bit misleading. Unless you were extremely slow before, Google says that improving page speed should not impact your rankings.<\/p>\n\n\n\n<p>So why might you see more visitors?<\/p>\n\n\n\n<p>The answer is that the analytics tag probably fired sooner than before, and was able to record more people before they leave a page.<a><\/a><\/p>\n\n\n\n<h2>How Fast Should My Page Load?<\/h2>\n\n\n\n<p>There\u2019s&nbsp;<a href=\"https:\/\/youtu.be\/7HKYsJJrySY?t=32\" target=\"_blank\" rel=\"noreferrer noopener\">no official threshold<\/a>. One of the common recommendations is that your site should load in less than three seconds. That likely comes from&nbsp;<a href=\"https:\/\/www.thinkwithgoogle.com\/marketing-resources\/data-measurement\/mobile-page-speed-new-industry-benchmarks\/\" target=\"_blank\" rel=\"noreferrer noopener\">a Google study<\/a>&nbsp;saying that 53% of mobile visitors leave a page that takes longer than three seconds to load.<\/p>\n\n\n\n<p>This recommendation is also most likely based on the Speed Index metric, which we\u2019ll talk about later, but that\u2019s just my speculation based on what was a popular measure at the time of the study. I don\u2019t believe that Google has ever mentioned a particular metric when giving a number for page speed. Usually, the recommendations from Google representatives are generic like \u201cmake sites fast for users\u201d or \u201cmake sites as fast as possible.\u201d<a><\/a><\/p>\n\n\n\n<h2>How A Page Is Built<\/h2>\n\n\n\n<p>To understand how to improve your page speed, you need to know how a browser constructs a page. For this, we\u2019re mainly going to be looking at Waterfall charts to see what resources are loading. You can also see this in your browser by using \u201cright-click\u201d &gt; Inspect &gt; and bringing up the Network tab when loading a page.SIDENOTE.&nbsp;I\u2019m going to be using&nbsp;<a href=\"https:\/\/www.webpagetest.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.webpagetest.org\/<\/a>&nbsp;for a lot of the images, and I\u2019ll link to the tests and list the settings where applicable.<\/p>\n\n\n\n<h3>Establishing Connections<\/h3>\n\n\n\n<p>The green, orange, and purple below represent the time it takes to establish a connection to the website. I\u2019ll go over each color below and what it represents.<img loading=\"lazy\" width=\"927\" height=\"305\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/1-establishing-connections-3.png\" alt=\"1 establishing connections 3\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/1-establishing-connections-3.png 927w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/1-establishing-connections-3-680x224.png 680w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/1-establishing-connections-3-768x253.png 768w\"><\/p>\n\n\n\n<p>Waterfall chart for the TwentyTwenty WordPress theme page from WebPageTest.org (<a href=\"https:\/\/www.webpagetest.org\/result\/200217_K1_60b853bca4c9153381a4288123f65c6a\/\" target=\"_blank\" rel=\"noreferrer noopener\">view it here<\/a>). Location: Dulles,&nbsp;VA. Device: Moto&nbsp;G4. Browser: Chrome. Speed: 3GSlow.<\/p>\n\n\n\n<h4>DNS&nbsp;(Green)<\/h4>\n\n\n\n<p>Domain Name System (DNS) is considered the phone book of the web. You give your browser a website name, and it checks with a&nbsp;DNS&nbsp;server to get an&nbsp;IP&nbsp;address (a location label) telling it where the website is hosted. It\u2019s just like storing a contact on your phone so you only have to know the name and not the phone number.<\/p>\n\n\n\n<p>Most of the time, your&nbsp;DNS&nbsp;is going to be with your domain registrar (where you bought the domain) or with your Content Delivery Network (CDN).<\/p>\n\n\n\n<p>Importantly, not all&nbsp;DNS&nbsp;providers are created equal. If every millisecond matters to you, you might want to consider using a different&nbsp;DNS&nbsp;provider. According to&nbsp;<a href=\"https:\/\/www.dnsperf.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">DNSPerf<\/a>, Cloudflare has an average query speed of 12.6 ms, whereas others like GoDaddy (46.04 ms) and Rackspace (90.38 ms) are slower on average. However, these numbers are not a completely accurate representation as the&nbsp;DNS&nbsp;can be cached (stored temporarily) in the browser when you\u2019ve already visited a website. The amount of time it\u2019s cached is referred to as the&nbsp;TTL&nbsp;(Time to Live). While the cache is still active, the browser won\u2019t have to connect to the&nbsp;DNS&nbsp;server to know where to go to access the website.<\/p>\n\n\n\n<h4>Connect (Orange)<\/h4>\n\n\n\n<p>This is where the browser is establishing a connection with the hosting server. Transmission Control Protocol \/ Internet Protocol (TCP\/IP) is complicated, but just think about how you get to work. It\u2019s likely not a straight line; you have to make turns, and there will be areas with higher traffic. You may even re-route or make some wrong turns. That\u2019s sort of how this works; it\u2019s routing from your browser to the server and back.<\/p>\n\n\n\n<p>If the time to connect is long, it could be one of many issues. On unstable connections, packet loss might occur and will have to be re-sent. This is akin to missing your turn on a roundabout and having to go around again. The problem could also be with the routing of the request through the network. How many hops it has to take, how far it has to go, how much other traffic is on the network are similar to how many turns you need to take, how far from work you are, and how many other cars are on the road that might slow you down. There\u2019s also rate-limiting and connection capacity on the server, which would be similar to a tunnel that only allows so many cars though it at a time.<\/p>\n\n\n\n<p>A lot of these issues are solved by making the distance to the server shorter and using more intelligent routing\u2014which many CDNs can do. With a network of servers around the world, visitors can usually connect to a close one. Some&nbsp;CDN&nbsp;providers also manage large amounts of internet requests and can see in real-time where there may be bottlenecks (traffic). If they see a faster option, they can reroute the traffic\u2014just like how a&nbsp;GPS&nbsp;would reroute you around a traffic jam.<\/p>\n\n\n\n<h4>Secure Sockets Layer (SSL) (Purple)<\/h4>\n\n\n\n<p>For sites establishing a secure connection (<a href=\"https:\/\/ahrefs.com\/blog\/http-vs-https-for-seo\/\">HTTPS<\/a>), this is where the browser and server are agreeing on the&nbsp;TLS&nbsp;(Transport Layer Security) protocol version, the ciphersuite (level of security), and verifying the certificate (to make sure the site is the one it says it is).<\/p>\n\n\n\n<p>You might be thinking that you can make your website faster by just not using&nbsp;HTTPS. That\u2019s partially true\u2014at least for the connection part. But there are other benefits to being on&nbsp;HTTPS&nbsp;like the fact that browsers don\u2019t let you use&nbsp;HTTP\/2 (H2) without&nbsp;HTTPS.&nbsp;H2&nbsp;has some advantages like persistent connections, so it doesn\u2019t have to keep opening a new connection for files on the same server. The headers within those requests are also smaller than in&nbsp;HTTP\/1.1, and multiple files can be transferred simultaneously. In most cases, sites using&nbsp;HTTPS&nbsp;and&nbsp;H2&nbsp;will be faster than sites on&nbsp;HTTP.<\/p>\n\n\n\n<p>Generally, the most significant gains you\u2019ll get here come from upgrading your protocol (TLS&nbsp;1.3 is faster than&nbsp;TLS&nbsp;1.2, for instance) and implementing&nbsp;HTTP&nbsp;Strict Transport Security (HSTS), which tells the browser always to use a secure connection. The browser changes the requests from&nbsp;HTTP&nbsp;to&nbsp;HTTPS&nbsp;without having to contact the server and do a redirect. In the image below, the redirect from&nbsp;HTTP&nbsp;to&nbsp;HTTPS&nbsp;and the time that took would be eliminated by using&nbsp;HSTS.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/2-secure-sockets-layer-3.png\" alt=\"2 secure sockets layer 3\" class=\"wp-image-34710\"\/><\/figure>\n\n\n\n<p>You may even want to look into using&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/HTTP\/3\" target=\"_blank\" rel=\"noreferrer noopener\">HTTP\/3<\/a>&nbsp;for even faster connections. However, support for this protocol is still in the early stages, and\u2014at least at the time of writing\u2014is probably not yet a viable option.IMPORTANT: DEVICE, LOCATION, AND NETWORK MATTER<\/p>\n\n\n\n<p>Consider this, connecting to a website on a mid-grade smartphone with a slow&nbsp;3G&nbsp;connection takes ~2 seconds. On the same phone with an&nbsp;LTE&nbsp;connection, it\u2019s cut down to ~0.41 seconds. On a desktop computer with normal speeds, it\u2019s less than 0.1 seconds to make that connection.<\/p>\n\n\n\n<p>Keep that in mind if you see longer connection times as it may be due to limited bandwidth or processing power of the test device. These factors\u2014along with caching\u2014are important. They can help you explain to someone who might pull out their latest smartphone, connected to WiFi, with all the files needed to load the page already cached on their device (we\u2019ll talk about this in another section) that the way they are experiencing the site is under ideal conditions and not how most people will experience it.<\/p>\n\n\n\n<h3>Downloading And Processing&nbsp;HTML<\/h3>\n\n\n\n<p>The&nbsp;HTML&nbsp;code of a page is what is initially downloaded by a browser. This is the information you see when you right-click on a website and go to \u201cView Page Source.\u201d Once a connection has been established, and the browser gets the first bit of information back from the server, we reach the Time To First Byte (TTFB), which is the typical measure for the initial response time. As represented by the orange lines below, this is the time from the start of the&nbsp;HTML&nbsp;request (light blue) to the time when the&nbsp;HTML&nbsp;starts to download (dark blue).<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/3-downloading-html-3.png\" alt=\"3 downloading html 3\" class=\"wp-image-34709\"\/><\/figure>\n\n\n\n<p>If there\u2019s a delay for&nbsp;TTFB, it could be due to database queries, server resources, waiting for a Server Side Render (SSR) to complete, or other things typically involved with creating dynamic content. The download time will depend on things like the connection and file size.<\/p>\n\n\n\n<p>This is also where the browser also starts to construct a page. When the&nbsp;HTML&nbsp;is downloaded, the browser parses it into the Document Object Model (DOM), which is how a computer understands the structure of the content. That parsing process uses the browser\u2019s main thread to process user actions and paint the page, run JavaScript, and perform layouting, reflows, and garbage collection. For now, just know that this main thread exists and handles a lot of different tasks. We\u2019ll cover this a bit more later.<\/p>\n\n\n\n<p>If you see a gap between&nbsp;HTML&nbsp;and the next request, the most likely cause is that the&nbsp;CPU&nbsp;is busy processing the&nbsp;HTML&nbsp;to build the&nbsp;DOM. Since it\u2019s the&nbsp;CPU, this is again dependent on the device being used, so you can test with a more powerful device to see if that gap still exists.<\/p>\n\n\n\n<p>For the&nbsp;HTML&nbsp;and other file types like&nbsp;CSS&nbsp;and JavaScript, you can cut the time down by using less code, minification to remove unnecessary characters like comments and white space from the code, and compression to reduce the size of the files. The point is to make the file download smaller so this part of the load would be faster. However, there isn\u2019t only one way to do minification and compression. In many instances, this is handled by the&nbsp;CDN&nbsp;or the server (Apache or Nginx are common servers), or by a plugin\/module\/package. You can find more information on implementing compression&nbsp;<a href=\"https:\/\/web.dev\/uses-text-compression\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>&nbsp;and minification&nbsp;<a href=\"https:\/\/web.dev\/reduce-network-payloads-using-text-compression\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<h3>Handling Additional Connections<\/h3>\n\n\n\n<p>When the&nbsp;HTML&nbsp;has been downloaded, references to other files and other servers will be processed, and new connections will start. This is typically where other files like JavaScript,&nbsp;CSS, Images, and Fonts are added to the mix. Things can get crazy here as some files reference other files, and we start chaining connections and file downloads. Take a look at the Request Map below for Forbes.com. Each point is an individual file request, and each line is where one file is referencing another file that has to be downloaded. Overall it\u2019s 363 requests across 128 connections.<img loading=\"lazy\" width=\"1600\" height=\"762\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/requestmap_https___www.forbes.com_-3.png\" alt=\"requestmap https   www.forbes.com  3\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/requestmap_https___www.forbes.com_-3.png 1600w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/requestmap_https___www.forbes.com_-3-680x324.png 680w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/requestmap_https___www.forbes.com_-3-768x366.png 768w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/requestmap_https___www.forbes.com_-3-1536x732.png 1536w\"><\/p>\n\n\n\n<p>Source:&nbsp;<a href=\"https:\/\/requestmap.herokuapp.com\/render\/200227_K2_cb725ce6494dbae765a55b45e6062468\/?dark=0#\" target=\"_blank\" rel=\"noreferrer noopener\">RequestMap<\/a><\/p>\n\n\n\n<h4>Use the Same Server for Requests When Possible<\/h4>\n\n\n\n<p>It used to be a best practice to host resources on cookieless domains that were not the same as the main domain, and sometimes there\u2019d be a benefit to using multiple domains (a process called domain sharding) because of connection request limits set by the browser.<\/p>\n\n\n\n<p>Since&nbsp;HTTP\/2, that has not been a best practice. You should use the same server for requests, if possible.<\/p>\n\n\n\n<p>For example, take&nbsp;<em>cdn.ahrefs.com<\/em>&nbsp;in the waterfall chart below.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/4-same-server-3.png\" alt=\"4 same server 3\" class=\"wp-image-34715\"\/><\/figure>\n\n\n\n<p>If that file were hosted on ahrefs.com, then it wouldn\u2019t even have to make the connection. It\u2019s being delayed by the time to make the&nbsp;DNS&nbsp;connection, to connect, and to negotiate the security handshake. Without the extra hoops to jump through, we would have the file earlier, which means the page would load even faster.<\/p>\n\n\n\n<p>However, while self-hosting many files like fonts can lead to gains, there may be other trade-offs like caching (storing a copy of a file) where browsers may sometimes have common resources cached. For example, if I visited one website that called a font from Google Fonts and then went to another website using the same font, I might have that file cached locally already and not have to download it again.<\/p>\n\n\n\n<h4>Use Preconnect or DNS-Prefetch (If You Use Another Server)<\/h4>\n\n\n\n<p>If you\u2019re going to use a different server, Preconnect to servers that contain files needed early in the page load. This is going to make the connection to another server earlier than it would ordinarily happen. See below how one of the connections for Amazon starts before the&nbsp;HTML&nbsp;is even finished processing.<br><img loading=\"lazy\" width=\"364\" height=\"141\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/5-preconnect-dns-prefetch-3.png\" alt=\"5 preconnect dns prefetch 3\"><\/p>\n\n\n\n<p><strong>Code example:<\/strong><br><code>&lt;link rel=\"preconnect\" href=\"https:\/\/site.com\"&gt;<\/code><\/p>\n\n\n\n<p>There\u2019s also DNS-prefetch if you just want to handle that part of the connection early. The green (DNS) part would connect early, but the rest of the connection will happen later.&nbsp;<a href=\"https:\/\/caniuse.com\/#search=dns-prefetch\" target=\"_blank\" rel=\"noreferrer noopener\">DNS-prefetch has better support<\/a>&nbsp;than&nbsp;<a href=\"https:\/\/caniuse.com\/#feat=link-rel-preconnect\" target=\"_blank\" rel=\"noreferrer noopener\">preconnect<\/a>,&nbsp;but if you look at current usage statistics, the difference would be negligible. Preconnect is generally better if you know something from that server needs to be loaded early for the page to function. However, because preconnect requires more work for routing and security (the orange and purple), it\u2019s also going to be a bit more resource-intensive early on.<\/p>\n\n\n\n<p><strong>Code example:<\/strong><br><code>&lt;link rel=\"dns-prefetch\" href=\"\/\/asset1.com\"&gt;<\/code><\/p>\n\n\n\n<h3>How Browsers Render A Page<\/h3>\n\n\n\n<p>Before we continue and discuss options for optimization, I think it\u2019s best to understand a bit about how a browser renders a page. We have other files coming in now like&nbsp;CSS, JavaScript, Images, and Fonts, and the browser has to turn them, along with the&nbsp;HTML, into something useful. This is a dynamic process with new files being introduced, downloaded, parsed, and things being rearranged constantly to build the page. This process is commonly called the Critical Rendering Path and it looks like this:<\/p>\n\n\n\n<ol><li>HTML&nbsp;is processed into the&nbsp;DOM&nbsp;tree we mentioned earlier<\/li><li>CSS&nbsp;is parsed into the&nbsp;CSS&nbsp;Object Model (CSSOM), which tells the browser how everything is styled, padded, colored, sized, etc.<\/li><li>The&nbsp;CSSOM&nbsp;+&nbsp;DOM&nbsp;together make what is called the&nbsp;<a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/critical-rendering-path\/render-tree-construction\" target=\"_blank\" rel=\"noreferrer noopener\">Render Tree<\/a>.<img loading=\"lazy\" width=\"1150\" height=\"537\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-61.png\" alt=\"pasted image 0 61\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-61.png 1150w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-61-680x318.png 680w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-61-768x359.png 768w\"><\/li><li>Layouting happens, which is processing where each element will be within the browser viewport based on what\u2019s in the Render Tree.<img loading=\"lazy\" width=\"616\" height=\"281\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-58.png\" alt=\"pasted image 0 58\"><\/li><li>Pixels get painted on the screen so instead of a white screen, you see colors, shapes, text, and images.<\/li><\/ol>\n\n\n\n<p>SIDENOTE.&nbsp;A fun fact revealed by&nbsp;<a href=\"https:\/\/twitter.com\/g33konaut\" target=\"_blank\" rel=\"noreferrer noopener\">Martin Splitt<\/a>&nbsp;of Google is that Googlebot saves time and resources by not actually painting the pixels of a page. They have the information they need after layouting.<\/p>\n\n\n\n<p>The goal should be to get the required elements as early as possible to build the initial view as fast as we can. The visible load time is people\u2019s perceived view of a page\u2019s speed, i.e., how soon the content appears on the screen for them. What impacts this the most is how resources are loaded. It\u2019s usually the responsibility of the&nbsp;CMS&nbsp;or JavaScript Framework to help the browser prioritize when\/what\/how resources to load in what order to make the site appear faster. More on that in a bit.<\/p>\n\n\n\n<p>You also want to keep things simple and avoid complex calculations and lots of changes during the layout phase. Google has a more developer-focused guide for that&nbsp;<a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/rendering\/avoid-large-complex-layouts-and-layout-thrashing\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>, and another on&nbsp;<a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/rendering\/simplify-paint-complexity-and-reduce-paint-areas\" target=\"_blank\" rel=\"noreferrer noopener\">simplifying the painting process<\/a>.<\/p>\n\n\n\n<h4>Visual Load Metrics:<\/h4>\n\n\n\n<ul><li><strong>First Paint (FP)<\/strong>&nbsp;\u2014 browser renders anything for the first time.<\/li><li><strong>First Contentful Paint (FCP)&nbsp;<\/strong>&#8211; &nbsp;browser renders something from the&nbsp;DOM&nbsp;(Document Object Model), which could be text, an image, etc.<\/li><li><strong>First Meaningful Paint (FMP)<\/strong>&nbsp;\u2014 most important elements visually loaded.<\/li><li><strong>Largest Contentful Paint (LCP)<\/strong>&nbsp;\u2014 largest element above the fold loaded.<\/li><li><strong>Visually Complete<\/strong>&nbsp;\u2014 page is visually loaded.<\/li><li><strong>Speed Index&nbsp;<\/strong>&#8211; a calculated score for the visual load that takes into account multiple points in time.<\/li><li><strong>Cumulative Layout Shift (CLS)<\/strong>&nbsp;\u2014 Measures how much elements move around in the viewport during the load, or how stable the layout is. There\u2019s a nice guide to the causes of&nbsp;CLS&nbsp;<a href=\"https:\/\/gist.github.com\/paulirish\/5d52fb081b3570c81e3a\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/platform.twitter.com\/embed\/index.html?creatorScreenName=patrickstox&#038;dnt=false&#038;embedId=twitter-widget-0&#038;frame=false&#038;hideCard=false&#038;hideThread=false&#038;id=1223191694788702208&#038;lang=en&#038;origin=https%3A%2F%2Fahrefs.com%2Fblog%2Fadvanced-pagespeed-guide%2F&#038;siteScreenName=ahrefs&#038;theme=light&#038;widgetsVersion=219d021%3A1598982042171&#038;width=550px\n<\/div><\/figure>\n\n\n\n<h4>Seeing The Visual Load Along With The Waterfall Chart<\/h4>\n\n\n\n<p>On the Summary section in&nbsp;<a href=\"https:\/\/www.webpagetest.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">WebPageTest<\/a>, if you enabled recording then you should have a Video column in the main table with \u201cFilmstrip View.\u201d In this view, the red line at the top with the visual snapshots is at the same point as the red line at the bottom in the waterfall.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/6-visual-load-waterfall-3.png\" alt=\"6 visual load waterfall 3\" class=\"wp-image-34730\"\/><\/figure>\n\n\n\n<p>By moving the red line around to different points in the visual load, you should be able to look at what was just loaded in the waterfall that may have allowed different elements to display visually. This can help you determine what files you may need to prioritize.<\/p>\n\n\n\n<p>For example, if you see that most of your page is loaded except the text, but right after that a font is loaded and the text appears, then that\u2019s a good indication that font was required to show the text. You\u2019ll also be able to tell what images may be needed earlier with different viewports by simply looking at the generated screenshots.<\/p>\n\n\n\n<p>At the bottom of this chart is additional information such as&nbsp;CPU&nbsp;Utilization, Bandwidth, activity on the Browser Main Thread, and Interactivity. All of these charts again depend on the device and connection type. The information can be used to help troubleshoot different issues. For example, maybe there\u2019s simply too much being downloaded, which keeps the Bandwidth at the highest point. Or maybe there\u2019s a script using all of the&nbsp;CPU&nbsp;for a certain device, which can cause delays.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-65.png\" alt=\"pasted image 0 65\" class=\"wp-image-34727\"\/><\/figure>\n\n\n\n<h3>Filetype&nbsp;CSS<\/h3>\n\n\n\n<p>Where page speed gets complicated is that in many cases, there\u2019s no one right way to do things. Most methods have tradeoffs, and some are more complex to implement and maintain. You have to decide what\u2019s easiest, fastest, and best for you in your circumstances.<\/p>\n\n\n\n<p>Looking at&nbsp;CSS&nbsp;files, they\u2019re render-blocking by default, meaning that they need to be downloaded and processed before a page displays content to the user. If you cache (store a copy of the file, covered later in the article), then that file can be re-used for subsequent page loads. That means it won\u2019t have to be downloaded again, and the next views should be faster.<\/p>\n\n\n\n<p>Most of the speed tools test with the first view, so a lot of what you see in a tool like&nbsp;<a href=\"https:\/\/developers.google.com\/speed\/pagespeed\/insights\/\" target=\"_blank\" rel=\"noreferrer noopener\">PageSpeed Insights<\/a>&nbsp;is representative of a first time user who only views one page and not someone who visits multiple pages or comes back to your website often. Your goal should be to both optimize that first view and subsequent views for users.<\/p>\n\n\n\n<h4>Loading&nbsp;CSS&nbsp;Asynchronously<\/h4>\n\n\n\n<p>You want to load important code as soon as possible, and we\u2019ll talk about a few options for that in a second, but the other part of this is you want the&nbsp;CSS&nbsp;not to block the render. To do this, we want to load the stylesheets needed later in the loading process as a different media type, which then gets applied to all types. It\u2019s tricking the browser by abusing how they handle the loading of specific link element attributes. What it\u2019s going to do is load the&nbsp;CSS&nbsp;without blocking rendering (because in this case, we\u2019re telling the browser this stylesheet is for print and not really for this version of the page), and then apply to all media types (things that aren\u2019t print) after it\u2019s loaded.<\/p>\n\n\n\n<p>For example, this:<\/p>\n\n\n\n<p><code>&lt;link rel=\"stylesheet\" href=\"\/my.css\"&gt;<\/code><\/p>\n\n\n\n<p>Becomes this:<\/p>\n\n\n\n<p><code>&lt;link rel=\"stylesheet\" href=\"\/my.css\" media=\"print\" onload=\"this.media='all'\"&gt;<\/code><\/p>\n\n\n\n<p>You can use this with all your&nbsp;CSS&nbsp;references. The tradeoff is that users may experience some flashing\/re-styling as some page elements may be painted before the&nbsp;CSS&nbsp;is applied. So when the&nbsp;CSS&nbsp;is applied, the screen may change where and how things are displayed.<\/p>\n\n\n\n<h4>Inline<\/h4>\n\n\n\n<p>Inline takes code needed to render content above the fold and delivers it with the&nbsp;HTML&nbsp;response instead of a separate file. This is typically going to be the fastest way to shorten the time it takes to render the initial view.<\/p>\n\n\n\n<p>The easiest way to think about this is you\u2019re taking critical parts of the&nbsp;CSS&nbsp;and&nbsp;JS&nbsp;files and putting it directly into the&nbsp;HTML. The initial&nbsp;HTML&nbsp;takes a little longer to download and parse, but the render of the page can now happen before all the other files are even downloaded.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-59.png\" alt=\"pasted image 0 59\" class=\"wp-image-34713\"\/><\/figure>\n\n\n\n<p>Inlining is probably going to get you the fastest render on the initial page load, but the tradeoff has traditionally been with caching. The code loaded in the&nbsp;HTML&nbsp;couldn\u2019t be re-used from the cache, so you would typically be loading some of the code twice: once with the&nbsp;HTML&nbsp;and again in the normal file that was typically cached. But if you inlined code for every page, that also meant subsequent pages would have extra code as well. This is advanced and involves the use of&nbsp;<a href=\"https:\/\/developers.google.com\/web\/fundamentals\/primers\/service-workers\" target=\"_blank\" rel=\"noreferrer noopener\">service workers<\/a>,&nbsp;but you can have both&nbsp;<a href=\"https:\/\/www.filamentgroup.com\/lab\/inlining-cache.html\" target=\"_blank\" rel=\"noreferrer noopener\">inlining and caching<\/a>. Combined with making the rest of the&nbsp;CSS&nbsp;asynchronous as we mentioned above, this is pretty much an ideal state.<\/p>\n\n\n\n<p>Remember that you can minify inline&nbsp;CSS&nbsp;code. As mentioned in the&nbsp;HTML&nbsp;section above, this removes some of the unnecessary spacing and extra characters to make the code smaller and faster to download.<\/p>\n\n\n\n<p>You probably don\u2019t want to inline all content from all the files. Be considerate and inline critical content only. You can technically inline all&nbsp;CSS&nbsp;and&nbsp;JS&nbsp;and even fonts and images, but you\u2019re going to end up with a giant&nbsp;HTML&nbsp;download where a lot of the code isn\u2019t used. That actually makes your website slower. If you have some smaller files of just a few&nbsp;KB&nbsp;and want to inline the whole thing for those, it\u2019s probably fine to do so.<\/p>\n\n\n\n<h5>Inline Critical&nbsp;CSS&nbsp;at scale:<\/h5>\n\n\n\n<p>You\u2019re going to want an automated system rather than doing this for every page. It might make sense to inline just the&nbsp;CSS&nbsp;for the homepage on WordPress themes since that typically has a different stylesheet than other pages. There\u2019s usually going to be some plugin\/module\/package or a version of Critical or Critical&nbsp;CSS. These packages exist for any taskrunner or packaging you may be using like Grunt, Gulp, Webpack, or Framework like React, Angular, Vue, and you can even find tutorials specific to WordPress or Drupal or even hand-coded pages. They\u2019re going to send a headless browser to the page to determine what&nbsp;CSS&nbsp;is actually critical for the page load at different sizes, and either give you the code or split the code into critical and non-critical elements so you can load them appropriately. A few examples:<\/p>\n\n\n\n<p><strong>Grunt:<\/strong><br><a href=\"https:\/\/github.com\/filamentgroup\/grunt-criticalcss\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/filamentgroup\/grunt-criticalcss<\/a><br><a href=\"https:\/\/www.npmjs.com\/package\/grunt-critical-css\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.npmjs.com\/package\/grunt-critical-css<\/a><br><a href=\"https:\/\/github.com\/bezoerb\/grunt-critical\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/bezoerb\/grunt-critical<\/a><\/p>\n\n\n\n<p><strong>Gulp:<\/strong><br><a href=\"https:\/\/github.com\/addyosmani\/critical\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/addyosmani\/critical<\/a><br><a href=\"https:\/\/www.npmjs.com\/package\/gulp-critical-css\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.npmjs.com\/package\/gulp-critical-css<\/a><\/p>\n\n\n\n<p><strong>Webpack:<\/strong><br><a href=\"https:\/\/github.com\/anthonygore\/html-critical-webpack-plugin\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/anthonygore\/html-critical-webpack-plugin<\/a><br><a href=\"https:\/\/github.com\/GoogleChromeLabs\/critters\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/GoogleChromeLabs\/critters<\/a><br><a href=\"https:\/\/github.com\/anthonygore\/html-critical-webpack-plugin\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/anthonygore\/html-critical-webpack-plugin<\/a><br><a href=\"https:\/\/www.npmjs.com\/package\/critical-css-webpack-plugin\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.npmjs.com\/package\/critical-css-webpack-plugin<\/a><\/p>\n\n\n\n<p><strong>React:<\/strong><br><a href=\"https:\/\/www.npmjs.com\/package\/react-critical-css\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.npmjs.com\/package\/react-critical-css<\/a>&nbsp;<br><a href=\"https:\/\/github.com\/addyosmani\/critical-path-css-tools\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/addyosmani\/critical-path-css-tools<\/a>&nbsp;<br><a href=\"https:\/\/github.com\/sergei-zelinsky\/react-critical-css\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/sergei-zelinsky\/react-critical-css<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>Angular:<\/strong><br><a href=\"https:\/\/github.com\/addyosmani\/critical-path-angular-demo\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/addyosmani\/critical-path-angular-demo<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>Vue:<\/strong><br><a href=\"https:\/\/github.com\/anthonygore\/vue-cli-plugin-critical\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/anthonygore\/vue-cli-plugin-critical<\/a>&nbsp;<br><a href=\"https:\/\/vuejsdevelopers.com\/2017\/07\/24\/critical-css-webpack\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/vuejsdevelopers.com\/2017\/07\/24\/critical-css-webpack\/<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>Drupal:<\/strong><br><a href=\"https:\/\/www.fourkitchens.com\/blog\/article\/use-gulp-automate-your-critical-path-css\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.fourkitchens.com\/blog\/article\/use-gulp-automate-your-critical-path-css\/<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>WordPress:<\/strong><br><a href=\"https:\/\/joe-watkins.io\/javascript\/inline-critical-css-with-wordpress\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/joe-watkins.io\/javascript\/inline-critical-css-with-wordpress\/<\/a>&nbsp;<br><a href=\"https:\/\/wordpress.org\/plugins\/wp-criticalcss\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/wordpress.org\/plugins\/wp-criticalcss\/<\/a><\/p>\n\n\n\n<p><strong>Hand-coded:<\/strong><br><a href=\"https:\/\/www.sitelocity.com\/critical-path-css-generator\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.sitelocity.com\/critical-path-css-generator<\/a>&nbsp;<br><a href=\"https:\/\/jonassebastianohlsson.com\/criticalpathcssgenerator\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/jonassebastianohlsson.com\/criticalpathcssgenerator\/<\/a>&nbsp;<\/p>\n\n\n\n<h4>Preload<\/h4>\n\n\n\n<p>If you\u2019re not going to inline the critical&nbsp;CSS, the next best option is arguably using Preload. Preload fetches requests earlier in the load, getting essential resources needed to display the page faster than usual. Preload sets the browser priority for preloaded assets as high and loads them asynchronously, so they don\u2019t block rendering. It also works across domains.<\/p>\n\n\n\n<p>The browser gives each request for a file a priority. The idea is to get files needed to display above the fold content earlier (at a higher priority) and defer those not required until later in the process. You can see the priority given to files in the Network tab in Chrome Dev Tools. Just right-click on the bar, select Priority, and add it as a column.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/7-preload-priority-3.png\" alt=\"7 preload priority 3\" class=\"wp-image-34726\"\/><\/figure>\n\n\n\n<p>What it\u2019ll do is take a file that may have started downloading later, and download it as soon as possible. Again, the other benefit is that where the preloaded file would have been render-blocking before, that will no longer be the case.https:\/\/platform.twitter.com\/embed\/index.html?creatorScreenName=patrickstox&amp;dnt=false&amp;embedId=twitter-widget-1&amp;frame=false&amp;hideCard=false&amp;hideThread=false&amp;id=846491532177768448&amp;lang=en&amp;origin=https%3A%2F%2Fahrefs.com%2Fblog%2Fadvanced-pagespeed-guide%2F&amp;siteScreenName=ahrefs&amp;theme=light&amp;widgetsVersion=219d021%3A1598982042171&amp;width=550px<\/p>\n\n\n\n<p>Combined with what we mentioned above for making&nbsp;CSS&nbsp;async, preload just adds another line that is meant to get the file faster by setting the browser priority higher than normal. This will also work for&nbsp;<a href=\"https:\/\/caniuse.com\/#feat=link-rel-preload\" target=\"_blank\" rel=\"noreferrer noopener\">browsers where preload is not supported<\/a>.<\/p>\n\n\n\n<p><strong>Code examples:<\/strong><\/p>\n\n\n\n<p><code>&lt;link rel=\"preload\" href=\"\/my.css\" as=\"style\"&gt;<\/code><br><code>&lt;link rel=\"stylesheet\" href=\"\/my.css\" media=\"print\" onload=\"this.media='all'\"&gt;<\/code><\/p>\n\n\n\n<h5>Choosing Which Files To Preload<\/h5>\n\n\n\n<p>Usually, you\u2019re going to have the main theme file that contains a lot of the&nbsp;CSS&nbsp;for the website. Devs will often name this after the theme, or call it \u201cstyle,\u201d or sometimes name it after the website itself. If you have trouble identifying this file or believe that other files may need to be preloaded as well, then the easiest way to check is by using the request blocking feature within Chrome Dev Tools. Open the Network tab and load a page to see the files requested. You can right-click on these to add them to the block list. When you reload a page, if the page still looks normal, then you probably didn\u2019t block a file needed for the above the fold content. When you get one of these that breaks how the page looks, that\u2019s an indication it\u2019s needed to render the content above the fold and is a file you want to preload.<br><img loading=\"lazy\" width=\"678\" height=\"868\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/8-block-request-url-3.png\" alt=\"8 block request url 3\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/8-block-request-url-3.png 678w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/8-block-request-url-3-332x425.png 332w\"><\/p>\n\n\n\n<h5>Things To Know About Preload<\/h5>\n\n\n\n<ol><li>You need crossorigin on fonts or you\u2019ll get a double load of the file.<\/li><li>You still need the normal file calls for&nbsp;JS&nbsp;+&nbsp;CSS, so don\u2019t delete those.<\/li><li>You can preload a font even if it\u2019s called in another file like a&nbsp;CSS&nbsp;file.<\/li><li>Be careful how much you preload. You can run into issues trying to preload too many files.<\/li><\/ol>\n\n\n\n<h4>Server Push<\/h4>\n\n\n\n<p>This was part of the&nbsp;HTTP\/2 (H2) specification. It allows a server to deliver a file without it being requested. So instead of a chain that might be&nbsp;HTML&nbsp;&gt;&nbsp;CSS&nbsp;&gt; Font, this allows a site to say I\u2019m going to need that font, just send it.<\/p>\n\n\n\n<p>Server Push is problematic, and I typically recommend against it, but if you are a great developer or have access to one, you can give it a shot. It requests files from the server on the same connection as the page request. Server push&nbsp;can load assets twice. There\u2019s a workaround using cookies and checking if you\u2019ve already pushed assets to users, but it\u2019s a complex implementation. There\u2019s another problem involving connection issues that can cause files not to load at all. With all of the extra work, you still may not see significant gains over preload because browsers check the page cache (where preload is) before the push cache.<\/p>\n\n\n\n<h3>Filetype JavaScript<\/h3>\n\n\n\n<p>JavaScript can also be complex, with a lot of options and a lot of considerations. Sometimes it is used to provide functionality, sometimes it\u2019s used to pull in the main content, and sometimes it\u2019s even used to make changes to the&nbsp;CSS. Furthermore, certain code may need other code to run properly. These are known as dependencies, and changing how JavaScript is loaded may end up breaking some functionality of the page.<\/p>\n\n\n\n<p>If JavaScript plays a critical role in content or the styling of the page, or if it\u2019s the core system\u2014as is the case with many JavaScript frameworks\u2014then many of the same rules as&nbsp;CSS&nbsp;apply as far as inlining and preloading. However, you also have the option of&nbsp;<a href=\"https:\/\/medium.com\/@baphemot\/whats-server-side-rendering-and-do-i-need-it-cb42dc059b38\" target=\"_blank\" rel=\"noreferrer noopener\">Server Side Rendering (SSR)<\/a>. This processes the code and renders a snapshot. For instance, if JavaScript is used to populate items on the page or for the menu, you may want this information earlier in the load or reduce some of the burden of the client\u2019s browser, you may want to use an&nbsp;SSR&nbsp;solution.<\/p>\n\n\n\n<p>The easiest way to see if JavaScript is needed on the page is to click the padlock in Chrome and open up Site settings. You\u2019ll see a list of Permissions with one being JavaScript where you can either Allow it or Block it. Blocking JavaScript, reloading the page, and comparing the site with and without JavaScript should show you if any elements are missing from the page or not. If something is missing, re-enable JavaScript and go through the same blocking process as we went through with&nbsp;CSS&nbsp;above to find out which files are critical to the rendered content.<\/p>\n\n\n\n<h4>Move to Footer<\/h4>\n\n\n\n<p>For inline scripts, you may consider moving them to the footer. Remember that JavaScript is parser blocking, which means it\u2019s blocking the&nbsp;HTML&nbsp;from being read. Moving these scripts to the footer ensures that much of the data can be processed before any blocking occurs. You have other options for script references that are probably better, such as defer and async.<\/p>\n\n\n\n<h4>Defer\/Async<\/h4>\n\n\n\n<p>Defer and Async are attributes that can be added to a script tag. Usually, a script being downloaded blocks the parser while downloading and executing. Async will let the parsing and download occur at the same time but still blocks during script execution. Defer does not block parsing during download and only executes after the&nbsp;HTML&nbsp;has finished parsing.<img loading=\"lazy\" width=\"1024\" height=\"512\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-60.png\" alt=\"pasted image 0 60\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-60.png 1024w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-60-680x340.png 680w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-60-768x384.png 768w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-60-400x200.png 400w\"><\/p>\n\n\n\n<p>Source:&nbsp;<a href=\"https:\/\/www.growingwiththeweb.com\/2014\/02\/async-vs-defer-attributes.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.growingwiththeweb.com\/2014\/02\/async-vs-defer-attributes.html<\/a>.<\/p>\n\n\n\n<h5>Defer\/Async code samples<\/h5>\n\n\n\n<p><strong>Normal:<\/strong><br><code>&lt;script src=\"https:\/\/www.domain.com\/file.js\"&gt;&lt;\/script&gt;<\/code><\/p>\n\n\n\n<p><strong>Async:<\/strong><br><code>&lt;script src=\"https:\/\/www.domain.com\/file.js\" async&gt;&lt;\/script&gt;<\/code><\/p>\n\n\n\n<p><strong>Defer:<\/strong><br><code>&lt;script src=\"https:\/\/www.domain.com\/file.js\" defer&gt;&lt;\/script&gt;<\/code><\/p>\n\n\n\n<p>Addy Osmani has a nice breakdown of blocking, async, defer, and preload and how it impacts browser priorities.https:\/\/platform.twitter.com\/embed\/index.html?creatorScreenName=patrickstox&amp;dnt=false&amp;embedId=twitter-widget-2&amp;frame=false&amp;hideCard=false&amp;hideThread=false&amp;id=1098122582472212481&amp;lang=en&amp;origin=https%3A%2F%2Fahrefs.com%2Fblog%2Fadvanced-pagespeed-guide%2F&amp;siteScreenName=ahrefs&amp;theme=light&amp;widgetsVersion=219d021%3A1598982042171&amp;width=550px<\/p>\n\n\n\n<h4>Responsiveness<\/h4>\n\n\n\n<p>Responsiveness is typically measured by First Input Delay (FID), which is the time from when a user interacts with your page until it can respond. Max Potential&nbsp;FID&nbsp;is the worst-case&nbsp;FID&nbsp;your users may experience. Many people typically measure Time To Interactive (TTI), which is how long it takes for a page to become fully interactive.<\/p>\n\n\n\n<p>Remember the things we mentioned earlier were happening on the main thread? Well, there\u2019s just one main thread, and JavaScript competes for those resources. While the thread is blocked, it can\u2019t respond to user input\u2014so the page feels slow. When a user clicks and the page doesn\u2019t do whatever action they requested promptly, they feel that delay. When this happens, your users may let you know and not in a nice way.<img loading=\"lazy\" width=\"916\" height=\"737\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-66.png\" alt=\"pasted image 0 66\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-66.png 916w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-66-528x425.png 528w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-66-768x618.png 768w\"><\/p>\n\n\n\n<p>Users complaining about the slowness of Twitter\u2019s app\u2026 on Twitter.<\/p>\n\n\n\n<p>What impacts responsiveness is JavaScript. All the JavaScript loaded for all the different things it can accomplish has to run in the same place.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-64.png\" alt=\"pasted image 0 64\" class=\"wp-image-34724\"\/><\/figure>\n\n\n\n<p>The image above is what the main thread looks like. Those red tick marks in the Performance tab in Chrome Dev Tools indicate where there may be some issues. Usually, tasks taking too much time to run on the main thread are the ones flagged. Each of those is where the page is overloaded with work and can\u2019t respond to user input promptly.<img loading=\"lazy\" width=\"1600\" height=\"900\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-62.png\" alt=\"pasted image 0 62\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-62.png 1600w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-62-680x383.png 680w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-62-768x432.png 768w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-62-1536x864.png 1536w\"><\/p>\n\n\n\n<p>Source:&nbsp;<a href=\"https:\/\/web.dev\/long-tasks-devtools\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/web.dev\/long-tasks-devtools<\/a><\/p>\n\n\n\n<p>While a task is running, a page can\u2019t respond to user input. This is the delay that is felt. The longer the task, the longer the delay experienced by the user. The breaks between tasks are the opportunities that the page has to switch to the user input task and respond to what they wanted.<\/p>\n\n\n\n<h4>Third-party tags<\/h4>\n\n\n\n<p>This is another report you can find in PageSpeed Insights. It shows the size and how long third-party scripts were blocking the main thread and impacting interactivity.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-67.png\" alt=\"pasted image 0 67\" class=\"wp-image-34729\"\/><\/figure>\n\n\n\n<p>Note that, especially with tag managers, some things may count toward the tag manager and not the script that\u2019s the problem. It might be part of the script in the container counting for a tag manager and not counted properly towards the third-party script.<\/p>\n\n\n\n<p>Use the size and main thread time to determine what you may be able to get rid of. Remember that most third-party scripts add some kind of functionality, tracking, or targeting, but rarely are they necessary for a page to function properly. Use your discretion to determine if the data gained is worth the extra load time for these scripts.<\/p>\n\n\n\n<h4>Common Sources of JavaScript Bloat:<\/h4>\n\n\n\n<ul><li>Jquery<\/li><li>A\/B testing systems<\/li><li>Heatmap systems<\/li><li>Real User Monitoring (RUM) systems<\/li><li>Live chat systems<\/li><\/ul>\n\n\n\n<h4>Cleanup Options:<\/h4>\n\n\n\n<ol><li><strong>Use fewer tracking\/scripts.<\/strong>&nbsp;This can be a hard decision as marketers like data, but sometimes the amount of data being collected is just absurd.<\/li><li><strong>Consolidate systems with similar functionality<\/strong>, like if you are running multiple analytics systems or multiple systems that have user information. Many programs have multiple functions, and sometimes you end up with scripts that have the same or similar functionality to another script when maybe you can do without one of them.<\/li><li><strong>Segmentation<\/strong>. For example, some A\/B testing systems will store and force you to load a list of all tests currently in the system, bloating the size of the download. Many times you can segment by section of the site and create smaller versions of the file.<\/li><li><strong>Server-side tracking instead of client-side.<\/strong>&nbsp;There are tradeoffs with tracking this way I won\u2019t cover here, but you can find a lot of resources on why you might use one over the other.<\/li><li><strong>Use web workers to move processing off the main thread.<\/strong>&nbsp;The downside of doing this is the web worker won\u2019t have access to the&nbsp;DOM. This is also fairly advanced and requires skilled developers.<\/li><li><strong>Service Workers \/ Edge Workers.<\/strong>&nbsp;I\u2019m excited for what the future holds with this technology. It\u2019s basically allowing&nbsp;JS&nbsp;to run at the Edge (or&nbsp;CDN&nbsp;level) instead of on the client browser. So before for an A\/B testing system, it might be that a file is downloaded and then processed and executed on the client browser. Because the test might overwrite parts of the&nbsp;DOM&nbsp;and happen later in the load, you might see visual flashes as things change. Now, you could basically pre-process the changes that were going to be made and deliver them inline with the&nbsp;HTML&nbsp;that\u2019s delivered to bots and users. Some platforms are already&nbsp;<a href=\"https:\/\/blog.cloudflare.com\/enhancing-optimizely-with-cloudflare-workers\/\" target=\"_blank\" rel=\"noreferrer noopener\">taking advantage of this<\/a>.<\/li><li><strong>Simply delay the execution of the load of a file<\/strong>&nbsp;if it\u2019s not needed right away or only initiate the file request based on an action like a click. For example, a live chat system probably isn\u2019t needed in the first five seconds of the page load, so delay it. You can also request the file after someone hovers or clicks on a button so it\u2019s not loaded with the initial page at all. Or use an image with a play button instead of embedding a YouTube video and only load in the YouTube video elements and play the content when a user clicks.<\/li><\/ol>\n\n\n\n<h4>Benefits of&nbsp;JS&nbsp;Frameworks:<\/h4>\n\n\n\n<p>JavaScript Frameworks like React, Angular, and Vue have some benefits over traditional systems.<\/p>\n\n\n\n<ul><li><strong>Tree shaking<\/strong>: Delivering only code used on the page. Any additional files or code not needed are not loaded, so it results in smaller files and smaller pages. It eliminates the code traditionally required for every other page and possibility.<\/li><li><strong>Code splitting<\/strong>: Splitting files into smaller chunks, so there are more opportunities for interactivity. For example, let\u2019s say you have a&nbsp;1MB&nbsp;JS&nbsp;file that runs as a long task on the main thread and blocks interactivity while it runs. You can split it into&nbsp;50KB&nbsp;chunks so tasks won\u2019t run as long, and there are more spaces in between at shorter periods where a page could respond to user input.<\/li><\/ul>\n\n\n\n<h3>Filetype Fonts<\/h3>\n\n\n\n<p>With fonts, you have many of the same options as we mentioned before (e.g., inlining or preloading a needed font). You\u2019ll find some code samples for preloading fonts&nbsp;<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Preloading_content\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>&nbsp;if you want to go that route. However, with fonts, what I would recommend is using font-display: swap;,&nbsp;which simply uses a default system font until the custom font is ready and then swaps in the custom font. This is relatively easy to do in your stylesheet.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@font-face {\n&nbsp; font-family: 'Whatever';\n&nbsp; font-display: swap;<br>}\n<\/pre>\n\n\n\n<p>If you\u2019re using Google fonts, it\u2019s even easier. All you need to do is add&nbsp;<code>&amp;display=swap<\/code>&nbsp;as a parameter in the&nbsp;URL.<\/p>\n\n\n\n<p><code>&lt;link href=\"https:\/\/fonts.googleapis.com\/css?family=Whatever&amp;display=swap\" rel=\"stylesheet\"&gt;<\/code><\/p>\n\n\n\n<h3>Filetype Images<\/h3>\n\n\n\n<p>The main concern with images is their size and weight. You want optimized images that are loading the right size for the right device and with the right quality.<\/p>\n\n\n\n<p>Images are loaded asynchronously, so they\u2019re not blocking the load of the page, but they can add to the weight and overall time to interactive.<\/p>\n\n\n\n<p>Another potential issue has to do with prioritization, where some images may not be prioritized correctly or prioritized before critical files like&nbsp;CSS&nbsp;and&nbsp;JS. I won\u2019t go into detail on this, but you can find more details and some information on how to troubleshoot&nbsp;<a href=\"https:\/\/github.com\/andydavies\/http2-prioritization-issues\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/blog.cloudflare.com\/http-2-prioritization-with-nginx\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>. There can also be conditions where many images load, maxing out resources such as the bandwidth and slowing down the overall page load.<\/p>\n\n\n\n<p>Many of the things we have talked about, like inline and preload can be used for images but with the same trade-offs like caching or complexity. The number one rule is not to use a lot of images or large images above the fold in your theme. You don\u2019t have to show your giant background images on mobile devices. People can live without them. If you must show the images, what I\u2019d recommend is preload, and this is covered pretty thoroughly by&nbsp;<a href=\"https:\/\/web.dev\/preload-responsive-images\/\" target=\"_blank\" rel=\"noreferrer noopener\">this guide<\/a>.<\/p>\n\n\n\n<p>There\u2019s a great guide covering image optimization and different formats at&nbsp;<a href=\"https:\/\/images.guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/images.guide\/<\/a>.<br>&nbsp;<br>Always do image optimization in a scalable way. There are lots of options to do this at different levels like with the&nbsp;CDN, server, by the&nbsp;CMS, with an&nbsp;API, etc. Here are a few options:<\/p>\n\n\n\n<p><strong>Image optimization CDNs:<\/strong><br><a href=\"https:\/\/www.akamai.com\/us\/en\/products\/web-performance\/image-manager.jsp\" target=\"_blank\" rel=\"noreferrer noopener\">Akamai Image Manager<\/a>&nbsp;<br><a href=\"https:\/\/www.imgix.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">imgix<\/a><br><a href=\"https:\/\/imageengine.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Image Engine<\/a><br><a href=\"https:\/\/cloudinary.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary<\/a><br><a href=\"https:\/\/uploadcare.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Uploadcare<\/a><\/p>\n\n\n\n<p><strong>Image optimization APIs:<\/strong><br><a href=\"https:\/\/shortpixel.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">ShortPixel<\/a><br><a href=\"https:\/\/docs.fastly.com\/api\/imageopto\/\" target=\"_blank\" rel=\"noreferrer noopener\">Fastly Image Optimizer<\/a><br><a href=\"https:\/\/kraken.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kraken.io<\/a><br><a href=\"https:\/\/tinypng.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">TinyPNG<\/a>&nbsp;<br><a href=\"https:\/\/imagify.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Imagify<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>GUI:<\/strong><br><a href=\"https:\/\/imageoptim.com\/mac\" target=\"_blank\" rel=\"noreferrer noopener\">ImageOptim<\/a>&nbsp;<br><a href=\"https:\/\/squoosh.app\/\" target=\"_blank\" rel=\"noreferrer noopener\">Squoosh<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>Command Line:<\/strong><br><a href=\"https:\/\/github.com\/imagemin\/imagemin-cli\" target=\"_blank\" rel=\"noreferrer noopener\">Imagemin<\/a>&nbsp;also has an&nbsp;<a href=\"https:\/\/www.npmjs.com\/package\/imagemin\" target=\"_blank\" rel=\"noreferrer noopener\">npm<\/a>&nbsp;module if you\u2019re using webpack, gulp, or grunt<\/p>\n\n\n\n<p><strong>JPEG:<\/strong><br><a href=\"https:\/\/github.com\/google\/guetzli\" target=\"_blank\" rel=\"noreferrer noopener\">Guetzli<\/a>&nbsp;<br><a href=\"https:\/\/github.com\/mozilla\/mozjpeg\" target=\"_blank\" rel=\"noreferrer noopener\">MozJPEG<\/a><br><strong>PNG:<\/strong><br><a href=\"https:\/\/pngquant.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">pngquant<\/a>&nbsp;<br><a href=\"https:\/\/github.com\/google\/zopfli\" target=\"_blank\" rel=\"noreferrer noopener\">Zopfli<\/a><\/p>\n\n\n\n<p><strong>GIF:<\/strong><br><a href=\"http:\/\/www.lcdf.org\/gifsicle\/\" target=\"_blank\" rel=\"noreferrer noopener\">Gifsicle<\/a><br><a href=\"https:\/\/github.com\/svg\/svgo\" target=\"_blank\" rel=\"noreferrer noopener\">SVGO<\/a>&nbsp;<\/p>\n\n\n\n<p><strong>WordPress\/Drupal<\/strong><\/p>\n\n\n\n<p>I don\u2019t have any particular recommendations. You\u2019ll find a lot of&nbsp;<a href=\"https:\/\/wordpress.org\/plugins\/search\/image+optimization\/\" target=\"_blank\" rel=\"noreferrer noopener\">options for WordPress<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/www.google.com\/search?rlz=1C1CHBF_enUS870US872&amp;sxsrf=ALeKk03S9uufWahcWFV2wrHV78Fp5FH8aQ%3A1583206144486&amp;ei=AM9dXp2QHbHl_Qbow6yoDg&amp;q=drupal+modules+image+optimization&amp;oq=drupal+modules+image+optimization&amp;gs_l=psy-ab.3..33i22i29i30.838.2415..3232...0.2..0.531.3785.2-5j3j2j1......0....1..gws-wiz.......0i71j35i39j0i22i30.X037XFlWovw&amp;ved=0ahUKEwidkOS-rv3nAhWxct8KHeghC-UQ4dUDCAs&amp;uact=5\" target=\"_blank\" rel=\"noreferrer noopener\">Drupal<\/a>.<\/p>\n\n\n\n<h4>Lazy Load Images<\/h4>\n\n\n\n<p>If someone tells you they need to \u201cdefer offscreen images,\u201d this is what you need. It is basically delaying the loading of images not above the fold because they\u2019re not needed yet. Once a user starts scrolling, the images will load in.<\/p>\n\n\n\n<p>I\u2019d say you want a library that uses IntersectionObserver but probably has a polyfill because of browser support. The most popular library for this is&nbsp;<a href=\"https:\/\/github.com\/aFarkas\/lazysizes\" target=\"_blank\" rel=\"noreferrer noopener\">lazysizes<\/a>,&nbsp;but you\u2019ll find many options for your setup.<\/p>\n\n\n\n<p>As of Chrome 76, lazy loading has been brought into the browser. I expect more browsers to do the same soon, but for now, we may want to use this method for Chrome with a polyfill for other browsers. You can find more info&nbsp;<a href=\"https:\/\/web.dev\/native-lazy-loading\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>. WordPress added&nbsp;<a href=\"https:\/\/make.wordpress.org\/core\/2020\/01\/29\/lazy-loading-images-in-wordpress-core\/\" target=\"_blank\" rel=\"noreferrer noopener\">lazy loading by default in version 5.4<\/a>.<\/p>\n\n\n\n<h4>Responsive\/Resized Images<\/h4>\n\n\n\n<p>This is all about serving the right image for the right screen. Loading a large image and then scaling it down just wastes time and resources. There are again a lot of automated solutions for this. For example, many CDNs will handle it, and there are also things like the&nbsp;<a href=\"https:\/\/www.npmjs.com\/package\/sharp\" target=\"_blank\" rel=\"noreferrer noopener\">sharp npm package<\/a>, the&nbsp;<a href=\"https:\/\/www.imagemagick.org\/script\/index.php\" target=\"_blank\" rel=\"noreferrer noopener\">ImageMagick&nbsp;CLI&nbsp;tool<\/a>, or various plugins\/modules for different systems.<\/p>\n\n\n\n<h4>Changing Image Formats<\/h4>\n\n\n\n<p>Different formats like webp can be better but are problematic due to browser support. You either have to do a lot of detection and swapping or use a service that does it for you. There are&nbsp;<a href=\"https:\/\/web.dev\/serve-images-webp\/\" target=\"_blank\" rel=\"noreferrer noopener\">plenty of guides<\/a>, but it\u2019s not something I\u2019d recommend most people tackle unless you can find an easy, automated way.<\/p>\n\n\n\n<h3>Page Size \/ Weight<\/h3>\n\n\n\n<p>This is the size of all the resources combined. Smaller pages are faster. We\u2019ve already talked about many of the improvements like minification, compression, and simply getting rid of anything not used. The less a page has to load initially, the faster the page will display.<\/p>\n\n\n\n<p>The goal should be a minimal amount of data to get the content above the fold loaded as quickly as possible. You can then load the rest of the information needed on the page after, all while keeping everything as small as possible. Problems usually come from unused code, images, and general website bloat related to functionality or tools. The reason I\u2019m giving this its own section is that you should be considerate of the overall amount of data your page is using.<\/p>\n\n\n\n<p>Check out&nbsp;<a href=\"https:\/\/whatdoesmysitecost.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">What Does My Site Cost<\/a>&nbsp;to see the approximate cost to users loading your page.<\/p>\n\n\n\n<h3>Other Web Performance Opportunities<\/h3>\n\n\n\n<p>There are a lot of options for things you can do to improve your page speed. I\u2019m going to cover a few more important ones, but there are many more opportunities out there because page speed is such a complex topic.<\/p>\n\n\n\n<h4>Caching<\/h4>\n\n\n\n<p>A cache is simply a stored copy of a file. Cached files can be reused on the next page without having to download them again.<\/p>\n\n\n\n<h5>Server Cache<\/h5>\n\n\n\n<p>This is where files come from when a browser requests them. Ideally, you want to hit the closest cache to the user. What I mean by that is that caches can be stored at many different levels with different TTLs set for each one that cause the cache to expire. There\u2019s a balance between caching for longer periods and having the content update quickly with changes. It\u2019s not quite that straightforward as you can clear the cache through different layers when an update is made, which is the ideal way to do this along with a cache warming system. Cache warming systems send a bot to rebuild the cache rather than waiting for a user to request the files, meaning a user never has to wait as the initial cache is built.<\/p>\n\n\n\n<p>A check usually goes something like:&nbsp;CDN&nbsp;cache &gt; Server cache (like Varnish) &gt; Origin (has to build the page on the fly). Generally, a higher level cache like the&nbsp;CDN&nbsp;is going to be faster, so you want most of your hits to be at that level.<\/p>\n\n\n\n<p>For example, on one of my sites on Cloudflare shown below, I have a little more than 50% cache hit rate for the&nbsp;CDN&nbsp;level. Unfortunately, that means many requests aren\u2019t served by the&nbsp;CDN&nbsp;and have to go back to the server-level cache. Or, if there\u2019s no current cached version there, it will have to build the page on the fly, which uses a lot of database resources and is going to be slower for a user.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-63.png\" alt=\"pasted image 0 63\" class=\"wp-image-34722\"\/><\/figure>\n\n\n\n<h5>Browser Cache<\/h5>\n\n\n\n<p>Even if you have a large website that tests poorly on page speed, there can be a considerable difference between the first and second load of a page or navigation between pages. A lot of what we\u2019ve talked about up until now was focused on making the initial load faster. This is what most testing tools see and is a user\u2019s first impression of your website. When a user visits a page, a browser can cache many of the files locally on the person\u2019s computer, which can be re-used for subsequent page views.<\/p>\n\n\n\n<p>For example, look at the difference between the first and second load for Ahrefs. Most of the files that had to be downloaded on the first load are cached on the client-side (browser), meaning the second load can just reuse the ones already downloaded to build the page. Cutting out the connection time and downloads means the page loads significantly faster. In this case, First Paint occurs roughly twice as fast in the second load.<\/p>\n\n\n\n<p><strong>1st load:<\/strong><br><img loading=\"lazy\" width=\"930\" height=\"877\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/waterfall.php_-7.png\" alt=\"waterfall.php  7\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/waterfall.php_-7.png 930w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/waterfall.php_-7-451x425.png 451w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/waterfall.php_-7-768x724.png 768w\"><\/p>\n\n\n\n<p><strong>2nd load:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/waterfall.php_-6.png\" alt=\"waterfall.php  6\" class=\"wp-image-34717\"\/><\/figure>\n\n\n\n<p>You\u2019ll see caching issues flagged in tools like Lighthouse as \u201cserve static assets with an efficient cache policy.\u201d Setting the length of time for the cache varies by system, but generally, what you need to do is use a Cache-Control&nbsp;HTTP&nbsp;response header. The max-age is the time you want it stored in seconds and can be set like:&nbsp;<code>Cache-Control: max-age=31536000<\/code><\/p>\n\n\n\n<p>Varvy has a&nbsp;<a href=\"https:\/\/varvy.com\/pagespeed\/cache-control.html\" target=\"_blank\" rel=\"noreferrer noopener\">guide for setting cache controls on different servers<\/a>&nbsp;that\u2019s worth reading.<\/p>\n\n\n\n<h4>Set a Performance Budget (Maybe)<\/h4>\n\n\n\n<p>A performance budget is a set of self-imposed limits on metrics that impact performance. It can be things like size, the number of a certain type of file, or some of the speed metrics we\u2019ve talked about. Setting a budget can help get the conversation started. Learn more&nbsp;<a href=\"https:\/\/web.dev\/performance-budgets-101\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<h4>Adaptive Loading<\/h4>\n\n\n\n<p>Adaptive loading adjusts what is loaded and when to make sites more progressive in how they load. Priority features and functionalities are loaded first, and the rest are loaded later based on things like the&nbsp;CPU, memory, or network speed. So, having fewer resources available means a stripped-down version of the site may be delivered, but people with more resources available will get the whole experience.<\/p>\n\n\n\n<p>One part of this is the Network Information&nbsp;API, which gives you information about the user\u2019s connection. You can change your images\/content or do things like turn off videos based on the network information of the incoming request. Many of the image CDNs do this using the&nbsp;<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Network_Information_API\" target=\"_blank\" rel=\"noreferrer noopener\">Network Information&nbsp;API<\/a>.<\/p>\n\n\n\n<h4>Use Other Resource Hints<\/h4>\n\n\n\n<h5>Prefetch<\/h5>\n\n\n\n<p>Prefetch is a resource hint that gets a file before it\u2019s needed. This can be for entire pages, scripts, or&nbsp;CSS&nbsp;files. One of the best ways to use this is with&nbsp;<a href=\"https:\/\/guess-js.github.io\/docs\/\" target=\"_blank\" rel=\"noreferrer noopener\">Guess.js<\/a>,&nbsp;which uses predictive prefetching. Guess connects to your Analytics and fetches the most likely next page based on current user behavior.<\/p>\n\n\n\n<h5>Preload<\/h5>\n\n\n\n<p>We\u2019ve talked about preload a bit already, but this is a slightly different use case. You can preload resources based on things like a&nbsp;<a href=\"http:\/\/instantclick.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">user hovering their mouse over a link<\/a>&nbsp;or links within the current viewport. While this can be somewhat resource-intensive, it ensures that the next page loaded will appear much faster.<\/p>\n\n\n\n<h4>AMP<\/h4>\n\n\n\n<p>AMP&nbsp;preloads in the&nbsp;SERP, so part of the site is already loaded before clicking.&nbsp;AMP&nbsp;has the benefit of having the visual load of the page done before even clicking.&nbsp;AMP&nbsp;looks faster than normal web pages when coming from the search results because the visible portion of the page is already loaded.<img loading=\"lazy\" width=\"1444\" height=\"498\" src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-68.png\" alt=\"pasted image 0 68\" srcset=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-68.png 1444w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-68-680x235.png 680w, https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/pasted-image-0-68-768x265.png 768w\"><\/p>\n\n\n\n<p>Source: https:\/\/www.ampproject.org\/latest\/blog\/why-amp-caches-exist\/<\/p>\n\n\n\n<p>There are many other performance enhancements and file size limitations within&nbsp;AMP&nbsp;that make it worth considering. Still, it is yet another system to maintain and has some other tradeoffs you probably want to look into before diving in.<a><\/a><\/p>\n\n\n\n<h2>Page Speed Testing And Tools<\/h2>\n\n\n\n<h3>Lab Data vs. Field Data<\/h3>\n\n\n\n<p><strong>Lab Data<\/strong>: Characteristics are a controlled environment, repeatable process, and control of settings. PageSpeed Insights is a great example. The test runs in the same environment with the same settings, and the results will be roughly the same with each run.<\/p>\n\n\n\n<p><strong>Field Data<\/strong>: Real User Monitoring (RUM) is how users experience the page. It takes into account everything like caching, devices, networks, etc., but is limited on metrics and the ability to debug.SIDENOTE.&nbsp;Be careful about how long you use Real User Monitoring (RUM) tools that allow you to collect field data. While these tools are great to see how the pages are loaded for users, they can also increase load times. Your goal is to make your site faster, and these can be helpful with diagnosing problems, but leaving them on can cause your pages to load slower.<\/p>\n\n\n\n<h3>Tools to Measure Page Speed<\/h3>\n\n\n\n<h4>Google Tools<\/h4>\n\n\n\n<ul><li><a href=\"https:\/\/testmysite.thinkwithgoogle.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">TestMySite<\/a>&nbsp;\u2014 Contains a speed scorecard where you can evaluate your speed vs. competitors, has an impact calculator so you can estimate the impact speed is having on your business, and allows you to build a report that includes these and some recommendations on things to focus on.<\/li><li><a href=\"https:\/\/developers.google.com\/web\/tools\/lighthouse\/\" target=\"_blank\" rel=\"noreferrer noopener\">Lighthouse<\/a>&nbsp;(in Chrome Dev Tools) \u2014 Allows for testing performance of pages and apps.<\/li><li><a href=\"https:\/\/developers.google.com\/speed\/pagespeed\/insights\/\" target=\"_blank\" rel=\"noreferrer noopener\">PageSpeed Insights<\/a>&nbsp;\u2014 Runs&nbsp;<a href=\"https:\/\/developers.google.com\/web\/tools\/lighthouse\/\" target=\"_blank\" rel=\"noreferrer noopener\">Lighthouse<\/a>&nbsp;and provides recommendations. Running Lighthouse in your browser is impacted by so many things like your computer, your network, extensions in your browser, etc. PageSpeed Insights allows for a fairly stable test environment that doesn\u2019t even use your server resources like a Lighthouse at scale setup would.<\/li><li><a href=\"https:\/\/developers.google.com\/web\/tools\/chrome-devtools\/\" target=\"_blank\" rel=\"noreferrer noopener\">Chrome Dev Tools<\/a>&nbsp;\u2014 Lots of useful features to see what and how a page is loading like the Network and Performance tabs.<\/li><li><a href=\"https:\/\/developers.google.com\/web\/tools\/chrome-user-experience-report\/\" target=\"_blank\" rel=\"noreferrer noopener\">Chrome User Experience Report (CrUX)<\/a>&nbsp;\u2014 A public dataset of real user experience data for those opted into sharing in Chrome that covers millions of websites. Field Data (data from actual users) for page speed.<\/li><li><a href=\"https:\/\/web.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">Web.dev<\/a>&nbsp;\u2014 Another Google testing tool backed by Lighthouse. It also has a section for learning more about page speed.<\/li><\/ul>\n\n\n\n<h4>Other Popular Speed Tools<\/h4>\n\n\n\n<ul><li><a href=\"https:\/\/www.webpagetest.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">WebPageTest<\/a><\/li><li><a href=\"https:\/\/www.sitespeed.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Sitespeed.io<\/a><\/li><li><a href=\"https:\/\/speedcurve.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">SpeedCurve<\/a><\/li><li><a href=\"https:\/\/calibreapp.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Calibre<\/a><\/li><li><a href=\"https:\/\/rigor.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Rigor<\/a><\/li><li><a href=\"https:\/\/newrelic.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">New Relic<\/a><\/li><li><a href=\"https:\/\/github.com\/akamai\/boomerang\" target=\"_blank\" rel=\"noreferrer noopener\">Boomerang<\/a><\/li><li><a href=\"https:\/\/batchspeed.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Batch Speed<\/a><\/li><li><a href=\"https:\/\/gtmetrix.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">GTmetrix<\/a><\/li><li><a href=\"https:\/\/tools.pingdom.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Pingdom<\/a><\/li><li><a href=\"https:\/\/speedmonitor.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">SpeedMonitor.io<\/a><\/li><\/ul>\n\n\n\n<h4>Site Audit &gt; Performance<\/h4>\n\n\n\n<p><a href=\"https:\/\/ahrefs.com\/site-audit\">Ahrefs\u2019 Site Audit tool<\/a>&nbsp;contains some information about page speed as well. There\u2019s a report for&nbsp;TTFB&nbsp;and for Load Time, which is how long it took us to download the page.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/ahrefs.com\/blog\/wp-content\/uploads\/2020\/03\/9-ahrefs-site-audit-3.png\" alt=\"9 ahrefs site audit 3\" class=\"wp-image-34720\"\/><\/figure>\n\n\n\n<p>What I personally tend to use:<\/p>\n\n\n\n<ol><li><strong><a href=\"https:\/\/developers.google.com\/speed\/pagespeed\/insights\/\" target=\"_blank\" rel=\"noreferrer noopener\">Pagespeed Insights<\/a><\/strong>&nbsp;\u2014 spot-checking individual pages. I also like their&nbsp;API. It allows for 25k tests per day at no cost and comes back with a lot of metrics, including CrUX page-level data. I will say that I don\u2019t pay much attention to the overall score, but I know a lot of people focus on this one metric. As we\u2019ve seen, speed is complex, and you may be improving on some metrics while not helping your score only because of&nbsp;<a href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1up5rxd4EMCoMaxH8cppcK1x76n6HLx0e7jxb0e0FXvc\/edit#gid=0\" target=\"_blank\" rel=\"noreferrer noopener\">how it\u2019s weighted<\/a>.<\/li><li><strong><a href=\"https:\/\/www.webpagetest.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">WebPageTest<\/a><\/strong>&nbsp;\u2014 the blocking function, filmstrips, video, waterfall, and requestmap. Also, their&nbsp;API&nbsp;for blocking at scale testing (with lighthouse reports also).<\/li><li><strong><a href=\"https:\/\/gtmetrix.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">GTmetrix<\/a><\/strong>&nbsp;\u2014 the chained requests report.<\/li><li><strong><a href=\"https:\/\/developers.google.com\/web\/tools\/chrome-user-experience-report\" target=\"_blank\" rel=\"noreferrer noopener\">CrUX<\/a><\/strong>&nbsp;\u2013 region research, histograms, competitor comparison.<\/li><li><strong><a href=\"https:\/\/web.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\">Web.dev<\/a><\/strong>&nbsp;\u2014 documentation is great.<\/li><\/ol>\n\n\n\n<h3>What Data is Google Using for Page Speed?<\/h3>\n\n\n\n<p>According to Google Webmaster Trends Analyst John Mueller in&nbsp;<a href=\"https:\/\/youtu.be\/7HKYsJJrySY?t=46\" target=\"_blank\" rel=\"noreferrer noopener\">this video<\/a>, Google uses the theoretical speed of a page (using lab data) and real field data from users who have tried to use those pages. He says this is similar to the data in the Chrome User Experience Report.<\/p>\n\n\n\n<p>The reality is there hasn\u2019t been any public confirmation of the source of the data they use. While John doesn\u2019t say that they use PageSpeed Insights and CrUX data, the data from those is likely representative of the data being used by Google. My best guess (and this is purely speculative) is that they use measures taken during their rendering process as lab data (potentially by lighthouse, but maybe not), and they likely have an internal resource similar to CrUX that they are using for the field data.<a><\/a><\/p>\n\n\n\n<h2>Estimating Impact of Changes<\/h2>\n\n\n\n<p>The easiest way to estimate impact is to make a static copy of a page. Copy the code to your server and test the page to get a baseline metric. Make changes to the page and test again, and you should get the approximate impact of the changes, so when you make them on your live site, you know the approximate impact.<\/p>\n\n\n\n<h2>Final Thoughts<\/h2>\n\n\n\n<p>You should make your site as fast as possible for users. Pick metrics that represent how a user experiences the load and interactivity of the page and improve on those. There isn\u2019t really a threshold where I would stop improving page speed, but there is often a stage where the benefit might not be worth the time, effort, costs, or potential tradeoffs (such as losing data from a tool). In general, I\u2019d try to be slightly faster than competitors.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are lots of tools to test page speed, and lots of different metrics to target. But do you understand how those optimizations work, or whether they\u2019re actually going to make your website faster?<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[30],"tags":[],"_links":{"self":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/1489"}],"collection":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1489"}],"version-history":[{"count":1,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/1489\/revisions"}],"predecessor-version":[{"id":1490,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=\/wp\/v2\/posts\/1489\/revisions\/1490"}],"wp:attachment":[{"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1489"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1489"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lvboard.infostore.in.ua\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}