Table of Contents
- Web Safe Fonts
- Font Display
- Unicode Ranges
- Preloading
- Google Fonts
- Images
- Using Alternative Packages
- Unused Dependencies
- Staying Up To Date With Dependencies
- Conclusion
Today, we will talk about the techniques that I used to speed up my very own website. I was quite curious about what tricks people were using to optimize their
blogs, portfolios to increase user experience. And, I'm wickedly obsessed when it comes to optimization. So I look further to see if there were any ways to optimize like
reducing bundle sizes, optimizing google fonts, using different bundles for the development environment and production environment, tricks to utilize for custom fonts.
Finally, here we're, on an optimized website referring to http://ogzhanolguncu.com/. Let's first see the GTmetrix score.
As can be seen, there isn't much to squeeze out in terms of performance. Now, we will dissect these processes step-by-step and see how to achieve a score like this.
Fonts
Web Safe Fonts
If you're aiming for the best you can get, do not even consider using anything but browsers Web Safe Fonts. By Web Safe Fonts I mean:
- Arial (sans-serif)
- Verdana (sans-serif)
- Helvetica (sans-serif)
- Tahoma (sans-serif)
- Trebuchet MS (sans-serif)
- Times New Roman (serif)
- Georgia (serif)
- Garamond (serif)
- Courier New (monospace)
- Brush Script MT (cursive)
These are highly accessible fonts pretty much for all the browsers since they already installed on your computer,
so prioritize them over Google Web Fonts or Adobe Fonts.
Font Display
@font-face {
font-family: ExampleFont;
src: url(/path/to/fonts/examplefont.woff) format('woff'), url(/path/to/fonts/examplefont.eot)
format('eot');
font-weight: 400;
font-style: normal;
font-display: optional;
unicode-range: U+0020-007F, U+0100-017F;
}
font-display
plays a huge role for Cumulative Layout Shift (CLS) and of course for the performance. So, best to go with
optional
for performance and swap
for decrease CLS.
Supported by all modern browsers.
Unicode Ranges
Specifying the unicode-ranges
beforehand tells the browsers to only download necessary characters that going to be used. Since we don't need characters
like Arabic, Greek, Hebrew, etc. Of course, if you are not using those characters 🙂.
Supported by all modern browsers. See the list for unicodes.
Preloading
<link
href="/fonts/Avenir-Roman.ttf"
as="font"
type="font/ttf"
rel="preload"
crossorigin="anonymous"
/>
The preload
means that you will need this font very soon after page loading, so load them first and then move onto others, before browsers' main rendering
kicks in. Therefore, preload
does not block the page's render and improves overall performance.
Google Fonts
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
When using Google fonts always use preconnect
first, the browser will start a new connection between origin and receiver to make things faster,
thus improving our websites' user experience and speed. And, pick the font-weights
you need because more font-weight
means bigger file to download, so choose wisely.
Images
There are not much to talk about images but always strive for smaller images you can get. For example, the image on my landing page is only 50kb, by the way, this is
the smallest it can get.
Use TinyPng to compress your images without losing quality.
Using Alternative Packages
Since this website runs on React only way to decrease the bundle size was to use Preact 3kB alternative for React.
If you are using Webpack as a bundler like me, you can follow the steps to implement this. By the way, I'm using preact for the production version.
- First, install preact
yarn add preact
- Then, configure your webpack bundler as shown below.
webpack: (config, { dev, isServer }) => {
if (!dev && !isServer) {
Object.assign(config.resolve.alias, {
react: 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat',
});
}
return config;
},
Apart from that example, you also analyze your packages through Google Lighthouse, which offers alternative smaller packages for current ones.
Unused Dependencies
Look through your dependencies inside package.json
, locate and delete unused ones. Because even if you don't use packages in package.json
they will still
be inside your final bundle, thus will make your bundle bigger, therefore make it load slower.
Staying Up To Date With Dependencies
Staying up to date with the latest dependencies may seem unnecessary at first, but sometimes developers improve their packages in terms of both speed and size. For example, Next.js 10's core packages have been reduced by 16%. They introduced a code-splitting strategy. All these happened because they added
their built-in Image component to the codebase. Before they have introduced this image component, I was using an external package to use images. I've omitted this one right away once I upgraded to Next.js 10.
Conclusion
- Use Web Safe Fonts.
-
Preload
your font file. - Preconnect to Google Fonts.
- Use
font-display: optional
orfont-display: swap
for performance and CLS. - Use only
unicode-range
you need. - Do not include
font-weight
you don't need to Google Fonts. - Compress your images.
- Use smaller alternative packages for your production bundle, such as Preact.
- Remove unused dependencies.
- Stay up to date with dependencies.
Thanks for reading 🥳🥳🥳.
Top comments (2)
Congrats! Always fun to read about personal audits/case studies!
📍 The first things I'd love to add so ppl who might read this remember: the quickest request is the one never made. So if you don't need it, don't load it. That said, you come in below 50 requests and more importantly under 1MB in resources, uncompressed, and i believe below 500kb compressed. Those are significant figures.
📍 I'd like to mention as well that you only have 1 image. This is also usually small, but again, if you don't need anything else, that's perfect. I'd mention 3 things re: the image. It does come in @ 50ish KB. I you wanted to go a few extra steps for fun, you could change formats. As is, your image w/ moderate quality edits would be 30KB as a WebP (supported everywhere), and 20kb as an AVIF (chrome, opera and FF desktop). Also, your image is 900kb per side. It sits in a 120px square container on mobile. reducing that image to say 300px per side for mobile would create a 9kb WebP and 7kb AVIF. This could be achieved w/ v little work. Last mention re: the image, it's req #15 in the load. Would love to see that image possibly preloaded and wonder if we could bump hat a little higher in the request chain. It could possibly improve your paint metrics, specifically the LCP. Esp if that image weight is small, this could come in pretty fast w/ a higher priority.
📍 req #4-#13 are all JS and wondering which of those could deferred instead of async'd? Are they needed to parse so early to display text and a single image?? Would be curious to see what comes of it. Are they critical resources is what I'm wondering.
📍 Curious how this would look hosting the fonts yourself, esp seeing that your LCP could see some improvement from it.
📍Your tag manager (req #19) seems to possibly be pushing the rest of the requests further out. Maybe that could be deferred as well.
Anyhow, these are super fun to read and thx for sharing your strategy here. 👏🏾👏🏾👏🏾. I love reading about these, and hearing how ppl work on it. As I mentioned last fall, perf is really investigative work. Not glamorous but fun!
When I see your comments about WebP and AVIF I immediately converted the image, thanks for that. By the way, right now I'm checking Next.js Image component to make that preloading thing possible. Due to lack of support, it was not possible back then.
For JS deferring, I don't think I can individually defer chucks but I'll look into it.
Any suggestion for self-hosted fonts? And, I definitely try to defer the tag manager.