Tag: Performance

Web Performance Checklist

The other day, I realized that web performance is an enormous topic covering so very much — from minimizing assets to using certain file formats, it can be an awful lot to keep in mind while building a website. It’s certainly far too much for me to remember!

So I made a web performance checklist. It’s a Notion doc that I can fork and use to mark completed items whenever I start a new project. It also contains a bunch of links for references.

This doc is still a work in progress. Any recommendations or links?Feel free to suggest something in the comments below!

The post Web Performance Checklist appeared first on CSS-Tricks.

CSS-Tricks

,

Maintaining Performance

Real talk from Dave:

I, Dave Rupert, a person who cares about web performance, a person who reads web performance blogs, a person who spends lots of hours trying to keep up on best practices, a person who co-hosts a weekly podcast about making websites and speak with web performance professionals… somehow goofed and added 33 SECONDS to their page load.

This stuff is hard even when you care a lot. The 33 seconds came from font preloading rather than the one-line wonder of font-display.

I also care about making fast websites, but mine aren’t winning any speed awards because I’ll take practical and maintainable over peak performance any day. (Sorry, world)

Direct Link to ArticlePermalink

The post Maintaining Performance appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

Performance Links

I’ve had a number of browser tabs open to articles all related to web performance and gosh darn it if blogging them is a way for me get some closure. They are all good!

Manuel Matuzovic, Why 543 KB keep me up at night:

Yes, I know, it depends. 543 KB aren’t always bad, but on that specific page there’s only a single image (the logo ~20 KB) and a single paragraph. So why then is the page still relatively large, where are the remaining 523 KB coming from?

Spoiler: it was the JavaScript. Also, I had no idea Google has a recommended ideal DOM that:

  • has less than 1500 nodes total.
  • has a maximum depth of 32 nodes.
  • has no parent node with more than 60 child nodes.

Next up, Performant front-end architecture (no byline):

Bundle splitting will result in more requests being made to load your app. But as long as the requests are made in parallel that’s not a big problem, especially if your site served over HTTP/2.

This is all about assuming the app is largely a client-side JavaScript site. I think there is a huge pile of low-hanging performance fruit, but it’s almost like a different list when talking about client-side JavaScript sites. It makes code-splitting one of the top priorities.


Jeremy Keith, Telling the story of performance:

Web Page Test is a terrific tool for measuring performance. It can also be used as a story-telling tool.

WPT ouputs video of the site loading. Put it side-by-side with a competitor and show it to the client.


CP Clermont, The Impact of Web Performance:

In this post, I’ll discuss what I did at ALDO to measure the revenue impact of web performance without having to spend time making performance improvements.

Not surprising that users with faster experiences generate more revenue. What is surprising is that it’s a lot more. Over 3x more on mobile and nearly 6x more on desktop.

The post Performance Links appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

In-Browser Performance Linting With Feature Policies

Here’s a neat idea from Tim Kadlec. He uses the Modheader extension to toggle custom headers in his browser. It also lets him see when images are too big and need to be optimized in some way. This is a great way to catch issues like this in a local environment because browsers will throw an error and won’t display them at all!

As Tim mentions, the trick is with the Feature Policy header with the oversized-images policy, and he toggles it on like this:

Feature-Policy: oversized-images ‘none’;

Tim writes:

By default, if you provide the browser an image in a format it supports, it will display it. It even helpful scales those images so they look great, even if you’ve provided a massive file. Because of this, it’s not immediately obvious when you’ve provided an image that is larger than the site needs.

The oversized-images policy tells the browser not to allow any images that are more than some predefined factor of their container size. The recommended default threshold is 2x, but you are able to override that if you would like.

I love this idea of using the browser to do linting work for us! I wonder what other ways we could use the browser to place guard rails around our work to prevent future mistakes…

Direct Link to ArticlePermalink

The post In-Browser Performance Linting With Feature Policies appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

The Unseen Performance Costs of Modern CSS-in-JS Libraries

This article is full of a bunch of data from Aggelos Arvanitakis. But lemme just focus on his final bit of advice:

Investigate whether a zero-runtime CSS-in-JS library can work for your project. Sometimes we tend to prefer writing CSS in JS for the DX (developer experience) it offers, without a need to have access to an extended JS API. If you app doesn’t need support for theming and doesn’t make heavy and complex use of the css prop, then a zero-runtime CSS-in-JS library might be a good candidate.

“Zero-runtime” meaning you author your styles in a CSS-in-JS syntax, but what is produced is .css files like any other CSS preprocessor would produce. This shifts the tool into a totally different category. It’s a developer tool only, rather than a tool where the user of the website pays the price of using it.

The flagship zero-runtime CSS-in-JS library is Linaria. I think the syntax looks really nice.

import { css } from 'linaria'; import fonts from './fonts';  const header = css`   text-transform: uppercase;   font-family: $  {fonts.heading}; `;  <h1 className={header}>Hello world</h1>;

I’m also a fan of the just do scoping for me ability that CSS modules brings, which can be done zero-runtime style.

Direct Link to ArticlePermalink

The post The Unseen Performance Costs of Modern CSS-in-JS Libraries appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Lightning-Fast Web Performance

,
[Top]

Bundling JavaScript for Performance: Best Practices

Performance advice from David Calhoun on how many scripts to load on a page for best performance:

[…] some of your vendor dependencies probably change slower than others. react and react-dom probably change the slowest, and their versions are always paired together, so they both form a logical chunk that can be kept separate from other faster-changing vendor code:

<!-- index.html --> <script src="vendor.react.[hash].min.js"></script> <script src="vendor.others.[hash].min.js"></script> <script src="index.[hash].min.js"></script>

Funny how times haven’t changed that much! Me, in 2012, talking about how many CSS files need to be loaded on any given page: One, Two, or Three. I split it into global, section-specific, and-page-specific so it was less about third-party code, although that could certainly apply, too.

Direct Link to ArticlePermalink

The post Bundling JavaScript for Performance: Best Practices appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Six Months Using Firebase Web Performance Monitoring

I don’t really think of Firebase as a performance monitoring tool (all I ever think about is auth and real-time data storage), but nevertheless, it totally has that feature.

Justin Ribeiro

[A] tool to track what real users in the wild are experiencing with an easy setup? Yes, please. […] I’ve been using Firebase web perf tracking since June on this very blog. Let’s take a look at the good, the bad, and the downright confusing portions of the Firebase web performance monitoring.

Justin talks about the good and bad of this particular product, but what I think is notable about this kind of performance tooling is that it is reflective of real users using your production site. A lot of performance tooling tests is just fancied up WebPageTest that runs your site once on probably-simulated browser conditions. I don’t see as much happening in the real user performance monitoring space.

I think I’d rank performance testing by type like this:

  1. Run simulated performance metrics in CI. Stop merge requests that break metrics/budgets.
  2. Measure real user monitoring in production.
  3. Run simulated performance metrics in production.

Direct Link to ArticlePermalink

The post Six Months Using Firebase Web Performance Monitoring appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Recipes for Performance Testing Single Page Applications in WebPageTest

WebPageTest is an online tool and an Open Source project to help developers audit the performance of their websites. As a Web Performance Evangelist at Theodo, I use it every single day. I am constantly amazed at what it offers to the web development community at large and the web performance folks particularly — for free.

But things can get difficult pretty quickly when dealing with Single Page Applications — usually written with React, Vue, Svelte or any other front-end framework. How can you get through a log in page? How can you test the performance of your users’ flow, when most of it happens client-side and does not have a specific URL to point to?

Throughout this article, we are going to find out how to solve these problems (and many more), and you’ll be ready to test the performance of your Single Page Application with WebPageTest!

Note: This articles requires an intermediate understanding about some of WebPageTest advanced features.

If you are curious about web performance and want a good introduction to WebPageTest, I would highly recommend the following resources:

The problem with testing Single Page Applications

Single Page Applications (SPAs) radically changed the way websites work. Instead of letting the back end (e.g. Django, Rails and Laravel) do most of the grunt work and delivering “ready-to-use” HTML to the browser, SPAs rely heavily on JavaScript to have the browser compute HTML. Such front-end frameworks include React, Vue, Angular or Svelte.

The simplicity of WebPageTest is what makes part of its appeal to developers: head to http://webpagetest.org/easy, enter your URL, wait a little, and voilà! Your performance audit is ready.

If you are building an SPA and want to measure its performance, you could rely on end-to-end testing tools like Selenium, Cypress or Puppeteer. However, I have found that none of these has the amount of performance-related information and easy-to-use tooling that WebPageTest offers.

But testing SPAs with WebPageTest can be complex.

In many SPAs, most of the site is protected behind a log in form. I often use Netlify for hosting my sites (including my personal blog), and most of the time I spend in the application is on authenticated pages, like the dashboard listing all my websites. As the information on my dashboard is specific to me, any other user trying to access https://app.netlify.com/teams/phacks/sites is not going to see my dashboard, but will instead be redirected to either a login or 404 page.

The same goes for WebPageTest. If I enter my dashboard URL into http://webpagetest.org/easy, the audit will be performed against the login page.

Moreover, testing and monitoring the performance of dynamic interactions in SPAs cannot be achieved with simple WebPageTest audits.

Here’s an example. Nuage is a domain name registrar with fancy animations and a beautiful, dynamic interface. When you search for domain names to buy, an asynchronous call fetches the results of the request and the results are displayed as they are retrieved.

As you might have noticed in the video above, the URL of the page does not change as I type my search terms. As a consequence, it is not possible to test the performance of the search experience using a simple WebPageTest audit as we do not have a proper URL to point to the action of searching something — only to an empty search page.

Some other problems can arise from the SPA paradigm shift when using WebPageTest:

  • Clicking around to navigate a webpage is usually harder than merely heading to a new URL, but it is sometimes the only option in SPAs.
  • Authentication in SPAs is usually implemented using JSON Web Tokens instead of good ol’ cookies, which rules out the option of setting authentication cookies directly in WebPageTest (as described here).
  • Using React and Redux (or other application state management libraries) for your SPA can mean that forms are harder to fill out programmatically, since using .innerText() or .value() to set a field’s value may not forward it to the application store.
  • As API calls are often asynchronous and various loaders can be used to indicate a loading state, those can “trick” WebPageTest into believing the page has actually finished loading when it has, in fact, not. I have seen it happen with longer-than-usual API calls (5+ seconds).

As I have faced these problems on several projects, I have come up with a range of tips and techniques to counter them.

The many ways of selecting an element

Selecting DOM elements is a key part of doing all sorts of automated testing, be it for end-to-end testing with Selenium or Cypress or for performance testing with WebPageTest. Selecting DOM elements allows us to click on links and buttons, fill in forms and more generally interact with the application.

There are several ways of selecting a particular DOM elements using native browser APIs, that range from the straightforward document.getElementsByClassName to the thorny but really powerful XPath selectors. In this section, we will see three different possibilities, ordered by increasing complexity.

Get an element by id, className or tagName

If the element you want to select (say, an “Empty Cart” button) has a specific and unique id (e.g. #empty-cart), class name, or is the only button on the page, you can click on it using the getElementsBy methods:

const emptyCartButton = document.getElementsById("empty-cart")[0]; // or document.getElementsByClassName(".empty-cart-button")[0] // or document.getElementsByTagName("button")[0] emptyCartButton.click();

If you have several buttons on the same page, you can filter the resulting list before interacting with the element:

const buttons = document.getElementsByTagName("button"); const emptyCartButton = buttons.filter(button =>   button.innerText.includes("Empty Cart") )[0]; emptyCartButton.click();

Use complex CSS selectors

Sometimes, the particular element you want to interact with does not present an interesting unicity property in either its ID, class or tag.

One way to circumvent this issue is to add this unicity manually, for testing purposes only. Adding #perf-test-empty-cart-button to a specific button is innocuous for your website markup and can dramatically simplify your testing setup.

However, this solution can sometimes be out of reach: you may not have access to the source code of the application, or may not be able to deploy new versions quickly. In those situations, it is useful to know about document.querySelector (and its variant document.querySelectorAll) and using complex CSS selectors.

Here are a few examples of what can be achieved with document.querySelector:

// Select the first input with the `name="username"` property document.querySelector("input[name='username']"); // Select all number inputs document.querySelectorAll("input[type='number']");  // Select the first h1 inside the <section> document.querySelector("section h1");  // Select the first direct descendent of a <nav> which is of type <img> document.querySelector("nav > img");

What’s interesting here is you have the full power of CSS selectors at hand. I encourage you to have a look at the always-useful MDN’s reference table of selectors!

Going nuclear: XPath selectors

XML Path Language (XPath), albeit really powerful, is harder to grasp and maintain than the CSS solutions above. I rarely have to use it, but it is definitively useful to know that it exists.

One such instance is when you want to select a node by its text value, and can’t resort to CSS selectors. Here’s a handy snippet to use in those cases:

// Returns the  that has the exact content 'Sep 16, 2015' document.evaluate(   "//span[text()='Sep 16, 2015']",   document,   null,   XPathResult.FIRST_ORDERED_NODE_TYPE,   null ).singleNodeValue;

I will not go into details on how to use it as it would have me wander away from the goal of this article. To be fair, I don’t even know what many of the parameters above even mean. However, I can definitely recommend the MDN documentation should you want to read on the topic.

Recipes for common use cases

In the following section, we will see how to test the performance in common use cases of Single Page Applications. I call these my testing recipes.

In order to illustrate those recipes, I will use the React Admin demo website as an example. React Admin is an open source project aimed at building admin applications and back offices.

It is a typical example of a SPA because it uses React (as the name suggests), calls remote APIs, has a login interface, many forms and relies on client-side routing. I encourage you to go take a quick look at the website (the demo account is demo/demo ) in order to have an idea of what we will be trying to achieve.

Authentication and forms

The authentication page of React Admin requires the user to input a username and a password:

The authentication screen of React Admin

Intuitively, one could take the following approach to filling in the form and submit:

const [usernameInput, passwordInput] = document.getElementsByTagName("input"); usernameInput.value = "demo"; // innerText could also be used here passwordInput.value = "demo"; document.getElementsByTagName("button")[0].click();

If you run these commands sequentially in a DevTools console on the login page, you will see that all fields are reset and the login request fails upon submitting by clicking the button. The problem comes from the fact that the new values we set with .value() (or .innerText()) are not kicked back to the Redux store, and thus not “processed” by the application.

What we need to do then is explicitly tell React that the value has changed so that it will update internal bookkeeping accordingly. This can be achieved using the Event interface.

const updateInputValue = (input, newValue) => {   let lastValue = input.value;   input.value = newValue;   let event = new Event("input", { bubbles: true });   let tracker = input._valueTracker;   if (tracker) {     tracker.setValue(lastValue);   }   input.dispatchEvent(event); };

Note: this solution is pretty hacky (even according to its own author), however it works well for our purposes here.

Our updated script becomes:

const updateInputValue = (input, newValue) => {   let lastValue = input.value;   input.value = newValue;   let event = new Event("input", { bubbles: true });   let tracker = input._valueTracker;   if (tracker) {     tracker.setValue(lastValue);   }   input.dispatchEvent(event); };  const [usernameInput, passwordInput] = document.getElementsByTagName("input");  updateInputValue(usernameInput, "demo"); updateInputValue(passwordInput, "demo");  document.getElementsByTagName("button")[0].click();

Hurrah! You can try it in your browser’s console—It works like a charm.

Translating this to an actual WebPageTest script (with scripting keywords, single line commands and tab-separated parameters) would look like this:

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  setEventName    Login      exec    const updateInputValue = (input, newValue) => {  let lastValue = input.value;  input.value = newValue;  let event = new Event("input", { bubbles: true });  let tracker = input._valueTracker;  if (tracker) {  tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    const [usernameInput, passwordInput] = document.getElementsByTagName("input")  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()

Note that clicking on the submit button leads us to a new page and triggers API calls, which means we need to use the execAndWait command.

You can see the full results of the test at this address. (Note: the results may have been archived by WebPageTest — you can, however, run the test again yourself!)

Here is a short video (captured by WebPageTest) in which you can see that we indeed passed the authentication step:

Navigating between pages

For traditional Server Rendered pages, navigating from one URL to the next in WebPageTest scripting is done via the navigate <url> command.

However, for SPAs, this does not reflect the experience of the user, as client-side routing means that the server has no role in navigation. Thus, hitting a URL directly would significantly slow down the measured performance (because of the time it takes for the JavaScript framework to be compiled, parsed and executed), a slowdown that the user does not experience when changing pages. As it is crucial to simulate the user flow the best we can, we need to handle the navigation on the client as well.

Hopefully, this is a lot simpler to do than filling up forms. We only need to select the link (or button) that will take us to the new page, and .click() on it! Let’s follow through our previous example, although now we want to test the performance of the Reviews list, and of a single Review page.

A user would typically click on the Reviews item on the left-hand navigation menu, then on any item in the list. Inspecting the elements in DevTools may lead us to a selection strategy as follows:

document.querySelector("a[href='#reviews']"); // select the Reviews link in the menu document.querySelector("table tr"); // select the first item in the Reviews list

As both clicks lead to page transition and API calls (to fetch the reviews), we need to use the execAndWait keyword for the script:

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  setEventName    Login  exec    const updateInputValue = (input, newValue) => {  let lastValue = input.value;  input.value = newValue;  let event = new Event("input", { bubbles: true });  let tracker = input._valueTracker;  if (tracker) {    tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    const [usernameInput, passwordInput] = document.getElementsByTagName("input")  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()  setEventName    Go to Reviews  execAndWait document.querySelector("a[href='#/reviews']").click()  setEventName    Open a single Review  execAndWait document.querySelector("table tbody tr").click()

Here’s the video of the complete script running on WebPageTest:

The audit result from WebPageTest shows the performance metrics and waterfall graphs for each step of the script, allowing us to monitor the performance of each API call and interaction:

What about Internet Explorer 11 compatibility?

WebPageTest allows us to select which location, browser and network conditions the test will use. Internet Explorer 11 (IE11) is among the available browser options, and if you try the previous scripts on IE11, they will fail.

This is due to two reasons:

The ES6 syntax problem can be overcome by translating our scripts to ES5 syntax (no arrow functions, no let and const, no array destructuring), which might look like this:

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  setEventName    Login  exec    var updateInputValue = function(input, newValue) {  var lastValue = input.value;  input.value = newValue;  var event = new Event("input", { bubbles: true });  var tracker = input._valueTracker;  if (tracker) {    tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    var usernameInput = document.getElementsByTagName("input")[0] exec    var passwordInput = document.getElementsByTagName("input")[1]  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()  setEventName    Go to Reviews  execAndWait document.querySelector("a[href='#/reviews']").click()  setEventName    Open a single Review  execAndWait document.querySelector("table tbody tr").click()

In order to bypass the absence of CustomEvent support, we can turn to polyfills and add one manually at the top of the script. This polyfill is available on MDN:

(function() {   if (typeof window.CustomEvent === "function") return false;   function CustomEvent(event, params) {     params = params || { bubbles: false, cancelable: false, detail: undefined };     var evt = document.createEvent("CustomEvent");     evt.initCustomEvent(       event,       params.bubbles,       params.cancelable,       params.detail     );     return evt;   }   CustomEvent.prototype = window.Event.prototype;   window.CustomEvent = CustomEvent; })();

We can then replace all mentions of Event by CustomEvent, set the polyfill to fit on a single line and we are good to go!

setEventName    Go to Login  navigate    https://marmelab.com/react-admin-demo/  exec    (function(){if(typeof window.CustomEvent==="function")return false;function CustomEvent(event,params){params=params||{bubbles:false,cancelable:false,detail:undefined};var evt=document.createEvent("CustomEvent");evt.initCustomEvent(event,params.bubbles,params.cancelable,params.detail);return evt}CustomEvent.prototype=window.Event.prototype;window.CustomEvent=CustomEvent})();  setEventName    Login  exec    var updateInputValue = function(input, newValue) {  var lastValue = input.value;  input.value = newValue;  var event = new CustomEvent("input", { bubbles: true });  var tracker = input._valueTracker;  if (tracker) {    tracker.setValue(lastValue);  }  input.dispatchEvent(event);};  exec    var usernameInput = document.getElementsByTagName("input")[0] exec    var passwordInput = document.getElementsByTagName("input")[1]  exec    updateInputValue(usernameInput, "demo") exec    updateInputValue(passwordInput, "demo")  execAndWait document.getElementsByTagName("button")[0].click()  setEventName    Go to Reviews  execAndWait document.querySelector("a[href='#/reviews']").click()  setEventName    Open a single Review  execAndWait document.querySelector("table tbody tr").click()

Et voilà!

General tips and tricks for WebPageTest scripting

One last thing I want to do is provide a few tips and tricks that make writing WebPageTest scripts easier. Feel free to DM me on Twitter if you have any suggestions!

Security first!

Remember to tick both privacy checkboxes if your script includes senstitive data, like credentials!

WebPageTest security controls

Browse the docs

The WebPageTest Scripting docs are full of features that I didn’t cover in this article, ranging from DNS Overriding to iPhone Spoofing and even if/else conditionals.

When you plan on writing a new script, I recommend to have a look at the available parameters first and see if any can help make your scripting easier or more robust.

Long loading states

Sometimes, a remote API call (say, for fetching the reviews) will take a long time. A loading indicator, such as a spinner, can be used to tell the user to wait a bit as something is happening.

WebPageTest tries to detect when a page has finished loading by figuring out if things are changing on the screen. If your loading indicator lasts a long time, WebPageTest might mistake it for an integral part of your page design and cut the audit before the API call returns — thus truncating your measures.

A way to circumvent this issue is to tell WebPageTest to wait at least a certain duration before stopping the test. This is a parameter available under the Advanced tab:

WebPageTest minimum test duration

Keeping your script (and results) human-readable

  • Use blank lines and comments (//) generously because single-line JavaScript commands can sometimes be hard to grasp.
  • Keep a multi-line version somewhere as your reference, and single-line everything as you are about to test. This helps readability. Like, a lot.
  • Use setEventName to name your different “steps.” This makes for more readable tests as it explicits the sequence of pages the audit goes through, and also appears in the WebPageTest results.

Iterating on your scripts

  • First, make sure that your script works in the browser. To do so, strip the WebPageTest keywords (the first word of every line of your script), then copy and paste each line in the browser console to verify that everything is working as expected at every step of the way.
  • Once you are ready to submit your test to WebPageTest, do it first with very light settings: only one run, a fast browser (cough — not IE11 — cough), no network throttling, no repeat view, a well-dimensioned instance (Dulles, VA, usually has good response times). This will help you detect and correct errors way faster.

Automating your scripts

Your test script is running smoothly, and you start getting performance reports of your Single Page App. As you ship new features, it is important that you monitor its performance regularly to catch regressions at the earliest.

To address this problem, I am currently working on Falco, a soon-to-be-open-sourced WebPageTest test runner. Falco takes care of automating your audits, then presents the results in an easy-to-read interface while letting you read the full reports when you need it. You can follow me on Twitter to know when it goes open source, and learn more about web performance and WebPageTest!

The post Recipes for Performance Testing Single Page Applications in WebPageTest appeared first on CSS-Tricks.

CSS-Tricks

, , , , , ,
[Top]

Get Peak WordPress Performance with Jetpack

The irony of web performance is that the average page weight of a site continues to go up year after year, despite us being more aware of the problem and having more tools at our disposal to fight it than ever.

To paraphrase Seinfeld, “we know how to fight page weight issues; we just don’t use the tools we have to fight page weight issues.”

That’s why Jetpack provides powerful features for all users at any plan level. They made it so that performance is integrated right into managing content on a WordPress site.

One of those things is lazy loading images. Lazy loading is an excellent technique to defer loading images until they are actually needed. So, an image never loads until the user actually scrolls to where it comes into display. That could potentially save a ton of server requests and precious bytes when waiting for a page to load. Jetpack includes lazy loading, even on free plans, so everyone has access to this performance boost.

And what’s the point of lazy loading anything if you don’t have somewhere to host the files? Well, Jetpack also offers unlimited static file and image hosting for every plan level. No more wondering how much storage is left on your server! You get an unlimited amount of space to store anything you need. That’s pretty awesome!

It gets even more awesome. That’s because the unlimited storage is part of a CDN that is designed to serve images from high-speed dedicated data centers that make downloads as fast and smooth as possible. Again, that’s free to everyone!

That makes Jetpack a super resource for combatting performance issues on a WordPress site. Hey, we use Jetpack here at CSS-Tricks and it’s a linchpin for so much of how this site works and operates. The performance benefits are a nice perk but it’s worth checking out everything it has to offer because there’s likely so much more you can leverage.

Get Jetpack

The post Get Peak WordPress Performance with Jetpack appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]