How to Make Fast Websites

7-minute read
Table of Contents

In today’s climate, we have the internet being dominated by WordPress and other CMS’s. It’s high time we addressed some of the bad habits web devs get into when making websites.

Although we do have the infrastructure to handle large websites with high traffic volumes, it is a waste of energy, and thus bad for the environment, to continue increasing the load demand by spinning up more bloated websites.

Here is how we can help the internet become a better place for everyone.

Make your own CSS

With styling systems like Bootstrap and Tailwind, it might be a bit taboo in some circles to hand craft your own stylesheets. Bootstrap provides a quick way to style components whereas Tailwind provides a streamlined approach to customize your HTML without ever having to open a CSS file - the latter is more flexible.

The limitations of these CSS frameworks is seen where one needs to build custom elements for their website. Bootstrap is not as flexible as Tailwind but tailwind can quickly bloat your HTML files. You will eventually have to step down to custom CSS in order to have the precision required to build the component without bloating your website files.

Remember that HTML files are what tend to be loaded upon each page visit so having a custom CSS file will not only save you time in not having you type a gazillion classes in your HTML files but it will also decrease the volume of data required to be transferred to the user’s device.

Avoid large custom CSS files

Keep class names short and comprehensive but also avoid going too deep in terms of nesting class selectors.

  • Bad:

.hero .info .title-block .heading{
}

Here we might read this as: “A hero div contains an info div with a title block div containing a heading div”. It gives us no idea if we should use an h1, h2, etc. with the heading class and it would definitely cause problems if we had to write custom CSS to force each heading level (h1, h2, …) to conform to the intended style.

  • Good:

.hero .info h1{
}

This helps you to work under the constraint: “every hero div needs an info div with an h1 inside”. This is the precursor to creating your own design system.

Component > Sheet > Document

The above example complies with the following ideas:

  • A document consists of headings, paragraphs and other basic HTML elements and provides a good way to present text information to the user
  • A sheet is a section of the webpage upon which the document is placed
  • The component contains sheets and shifts them around for responsiveness
  • We style the container then the sheet then the document elements which are placed upon the sheet

Customize only what you need to

It would be pointless to throw away all of the browser default styling then write custom CSS to fit the various HTML elements into a mould. Headings are already big. Why would you create a class to make paragraphs and any other non-heading element look like a heading instead of just using a heading?

Font size

Font size should be at least 1.15rem. 1.2rem is great!

Line height

1.3 for headings and 1.5 for body text makes text, especially larger sections, easier to read.

System font stacks

Use a font stack that already exists on your user’s device. Having users wait for the font files to download and swap in can lead to an overall bad user experience. Modern Font Stacks has some excellent options.

Cache-busting

Now that we have a tiny CSS file, we can set a ridiculously long caching period and only tell the user’s browser when to request the new version by cache-busting. This can be achieved by adding a parameter e.g. ?v=1.0.0 at the end of the url for the stylesheet. This works because the browser threats style.css?v=1.0.1 as a different file from style.css?v=1.0.0.

Frameworks such as Hugo can be used to automatically create a fingerprint of the stylesheet file and include that fingerprint in the name of the file specified in the link element e.g. style.min.0081be…1e488d73be.css. Thus, if the stylesheet file contents remain unchanged, the stylesheet linked in the header of each webpage will stay the same.

Optimize images

Images are the biggest culprit for slow load times and Cumulative Layout Shift (CLS). An image being 1000 pixels wide (referred to as intrinsic size) but only being shown with a width of 500 pixels (its rendered size) is wasteful.

Use formats like webp and avif

Webp and avif files are much more suited for websites as they provide seemingly no loss of quality but occupy a smaller space on disk. Having these formats means less server load and less use of bandwidth.

Avoid videos

Videos are best kept to a minimum as they have much larger file sizes even when compared to unoptimized images. If you are using a hosting provider that has a cap on your monthly server bandwidth then having many videos will only consume this bandwidth much quicker.

A CDN doesn’t fix bad design

Big files being sent from India are still big files when sent from Brazil. CDNs might help if you are trying to max out the delivery of files to be cached but they cannot be used to compensate for poor website architecture.

Watch out for redirects

If you use an href of /about for an anchor tag, the user will be redirected to /about/. It would be better to use the latter as the href to avoid the redirect.

Avoid complex build systems

Build systems aren’t exactly bad but they can introduce unnecessary overhead when making updates to your website.

Ease it with the analytics

Of course, you may be very curious as to who is using your brand new blazingly fast website, but there is a danger of including client-side tracking scripts to be loaded by your user’s device in order to spy on them. JavaScript takes time to be executed and thus tracking scripts can cause significant slow down in your site’s load time.

Apps like Goaccess allow for a lightweight server-side form of analytics that merely use access logs available on the server through services like nginx.

Compress your files

Because websites are simply the result of files being loaded on the user’s browser, it is a good idea to send smaller files over the network. This saves bandwidth and allows for faster loading speeds as less data needs to be delivered to the user.

Algorithms such as gzip and brotli produce smaller files to be sent over the network to the user’s device.

Use Lighthouse

Although the Lighthouse score doesn’t directly tell how well your website may rank in search results, it can be considered a direct metric for user on-page experience. Shifting links and images that jitter out of place will have a negative effect on your website’s Lighthouse score so be sure to pay close attention to each category.

Use Hugo for large static websites

Using a CMS such a WordPress, where each visit to a webpage corresponds to database query and the generation of an HTML from the data returned, is genuinely too much when it comes to creating a basic informational website.

Hugo is a static site generator that allows you full customization of HTML, CSS and JS, combined with the scalability of Go templating. You can independently custom headers and footers and the main sections of various sections in the content folder and then have content writers simply write markdown documents which are converted to the final web pages.

Hugo shortcodes

Hugo has a shortcode system where you can create custom HTML-ish tags to extend the functionality of markdown. Here is a multiple choice question:


What do you think?

1) Which is the best?

  1. WordPress
  2. Drupal
  3. Hugo

Here is the shortcode we typed into the markdown file:


{{<mcq>}}
Which is the best?
Hugo|WordPress|Drupal
{{</mcq>}}

Automatic image optimization

Hugo’s extended version can be configured to have shortcodes which produce various sizes of image files. We used this to create a shortcode that automatically populates the srcset of the HTML picture element:

/img/pepe.jpg This is an image of Pepe
The shortcode:


{{<optimg src="/img/pepe.jpg" caption="This is an image of Pepe">}}

Use Golang and Rust for large dynamic websites

These compiled languages are definitely the superior option when it comes to producing bulletproof blazingly fast dynamic websites. Many developers may avoid them because of the perceived difficulty of working with a more demanding language but the truth is clear - if we want to squeeze out performance from our web applications, we need to go to a lower level of control that interpreted languages simply cannot afford us.


Support us via BuyMeACoffee