Front-end Web Development Good Practices: Performance

Web-Performance.jpg
Web Performance

Web performance is about how fast and efficiently a website loads and works. It’s vital for a good user experience. It also affects how accessible and inclusive the web is, especially for users with less advanced hardware or slower internet. The goal is to make websites run smoothly on limited resources, instead of assuming that modern hardware and networks will fix performance problems. Web performance is a part of Web Accessibility.

Inspired by

This article is heavily influenced by this comprehensive article of HTMLHell and the Web Performance section of MDN Web Docs. It condenses these practices into a simpler format, providing examples of both effective and ineffective code.

Optimize images

Often, images are the biggest elements to load and they add a lot to the overall page size.

❌ Bad

The page contains a large image file that is linked directly and is not optimized

<img src="large-image.jpg" alt="Large Image">

✅ Good

Some improvements are applied

  • Use a smaller file size for the image, such as WebP format.
  • Use the loading="lazy" attribute to delay loading the image until it’s necessary, which improves the initial page load time.
  • Use the srcset attribute to provide different image files for different screen resolutions. This ensures that only required data is downloaded, saving bandwidth and enhancing performance on smaller screens.
<img src="large-image.webp" alt="Optimized Image" loading="lazy" 
  srcset="small-image.webp 500w, medium-image.webp 1000w, large-image.webp 2000w" />

Use built-in JavaScript APIs or small libraries over large JS libraries

JavaScript can often become the primary bottleneck when it’s used too much or not optimized correctly.

❌ Bad

Developers frequently import a whole library for just one function.

import _ from 'lodash';
let array = [1, 2, 3];
let reversed = _.reverse(array);

✅ Good

let array = [1, 2, 3];
let reversed = array.reverse();

It’s more efficient to use built-in JavaScript APIs.

Minimize Third-Party Code

Third-party code, tag managers, analytics tools, and embeds have a large effect on site performance. You need to think about removing them or assessing their impact to keep the site speed up.

❌ Bad

<!-- Multiple analytics tools -->
<script src="<https://www.analytics1.com/analytics.js>"></script>
<script src="<https://www.analytics2.com/analytics.js>"></script>
<script src="<https://www.analytics3.com/analytics.js>"></script>

✅ Good

<!-- Single analytics tool if needed -->
<script src="<https://www.analytics.com/analytics.js>"></script>

Utilize HTTP Caching Headers

Caching headers allow for the reuse of static assets such as images, CSS files, and JavaScript files, which minimizes the necessity for regular re-downloads.

❌ Bad

Every time a user visits or refreshes the page, the browser will download image.png.

const express = require('express');
const path = require('path');
const app = express();

app.get('/image.png', function (req, res) {
    res.setHeader("Cache-Control", "no-store");
    res.sendFile(path.join(__dirname, 'public', 'image.png'));
});

app.use(express.static(path.join(__dirname, 'public')));

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

✅ Good

If image.png is cached and is not more than one day old, the browser will use the cached version, avoiding the need for another download.

const express = require('express');
const path = require('path');
const app = express();

app.get('/image.png', function (req, res) {
    res.setHeader("Cache-Control", "public, max-age=86400"); // Cache for one day
    res.sendFile(path.join(__dirname, 'public', 'image.png'));
});

app.use(express.static(path.join(__dirname, 'public')));

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

Optimizing Web Fonts

You should host the font on your server, limit font files, possibly use Variable Fonts, and preload essential fonts.

❌ Bad

The page uses a web font (Roboto) hosted by an external service (Google Fonts). This results in Cumulative Layout Shift issues because the browser has to wait for the font to load before displaying the text.

<head>
  <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
</head>
<body>
  <p style="font-family: 'Roboto', sans-serif;">Hello, world!</p>
</body>

✅ Good

To remedy this, you’ll host the Roboto font on your server, ensuring immediate visibility of text with a fallback font, switching to Roboto once available. You’ll also use the preload directive to inform the browser of the immediate need for the Roboto font.

<head>
  <link rel="preload" href="/fonts/Roboto.woff2" as="font" type="font/woff2" crossorigin>
  <style>
    @font-face {
      font-family: 'Roboto';
      src: url('/fonts/Roboto.woff2') format('woff2');
      font-display: swap;
    }
  </style>
</head>
<body>
  <p style="font-family: 'Roboto', sans-serif;">Hello, world!</p>
</body>

Split CSS into separate modules

Modularly loading CSS allows you to load unneeded CSS later, reducing initial render-blocking and loading times.

❌ Bad

<!-- Only one file -->
<link rel="stylesheet" href="styles.css" />

✅ Good

<!-- Default styles that will always load -->
<link rel="stylesheet" href="styles.css" />

<!-- Only be loaded when the document is being printed -->
<link rel="stylesheet" href="print.css" media="print" />

<!-- Only be loaded by devices with narrow screens -->
<link
  rel="stylesheet"
  href="mobile.css"
  media="screen and (max-width: 480px)" />

Use a CDN

In some cases, using a Content Delivery Network (CDN) can improve the load time of the website, especially for distant users.

❌ Bad

<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
  <img src="images/logo.png" alt="Logo">
  <script src="scripts.js"></script>
</body>
</html>

✅ Good

<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
  <link rel="stylesheet" type="text/css" href="https://cdn.example.com/styles.css">
</head>
<body>
  <img src="https://cdn.example.com/images/logo.png" alt="Logo">
  <script src="https://cdn.example.com/scripts.js"></script>
</body>
</html>

Wrap up

Web performance, crucial for user experience and accessibility, involves optimizing website load times and efficiency. Key practices include optimizing image loading through smaller file sizes, lazy loading, and resolution-specific images, using built-in JavaScript APIs over large libraries, assessing the impact of third-party code, utilizing caching headers, hosting fonts on your own server and preloading important ones, modularly loading CSS, and using a Content Delivery Network (CDN) for static assets.

By Huong Nguyen

I am a full-stack software engineer. I have working experience with Java, Node.js, Angular, PostgreSQL, Jenkins, and OpenShift. I enjoy spending time with my son and wife on weekends. I am also a book lover. All posts and content I share solely represent my own views and do not represent the views of my employer.

Leave a comment

Your email address will not be published. Required fields are marked *