Good web page speed is no longer a luxury — it is a baseline requirement. Users expect a page to open within seconds, and every delay past three seconds costs you a meaningful share of your visitors. Google also uses speed as a ranking signal. The good news: making your page faster usually has less to do with expensive servers and more to do with applying the right techniques in the right order. In this guide I walk through the trio of lazy loading, minification and caching with concrete examples so you can cut load time dramatically.
Measure first: know what you are optimizing
Optimizing by guesswork is a waste of time. Start by measuring. The browser's built-in DevTools include a Lighthouse tab that scores your page's performance and lists the biggest bottlenecks. For more realistic data, Google's PageSpeed Insights shows both lab and field (real-user) data.
There are three Core Web Vitals metrics worth focusing on:
- LCP (Largest Contentful Paint): how long the largest content element takes to appear; under 2.5 seconds is good.
- INP (Interaction to Next Paint): response time to user interaction; aim for under 200 ms.
- CLS (Cumulative Layout Shift): the amount of visual shifting; under 0.1 is good.
Re-measure these metrics after every change so you can see what actually helped.
Lazy loading: only load what is visible
Downloading images, iframes and videos that sit off-screen on first load is wasteful. Lazy loading defers loading those resources until the user scrolls toward them. In modern browsers this is a single attribute:
<img src="product.jpg" alt="Product image" loading="lazy" width="800" height="600">
<iframe src="https://www.youtube.com/embed/..." loading="lazy"></iframe>
Always specify width and height; this lets the browser reserve space and prevents CLS. Do not add loading="lazy" to the first above-the-fold image — loading it as early as possible improves your LCP.
You can also defer heavy JavaScript components. For example, importing a module only when it is needed:
button.addEventListener('click', async () => {
const { openChart } = await import('./chart.js');
openChart();
});
This "code splitting" approach shrinks the initial bundle and reduces the time until the page is interactive.
Minify and compress: reduce the bytes
The whitespace, comments and long variable names we write so code stays readable are dead weight for the browser. Minification strips that excess from CSS and JavaScript files to reduce their size. Most build tools (Vite, esbuild, webpack) do this automatically in a production build:
npm run build # Vite applies minify + tree-shaking by default
On top of minification, add server-side compression. Gzip is widely supported, but Brotli usually gives a better ratio for text-based files. Enabling it in Nginx:
gzip on;
gzip_types text/css application/javascript image/svg+xml;
# If the Brotli module is installed:
brotli on;
brotli_types text/css application/javascript image/svg+xml;
Image format also makes a big difference. Using WebP or AVIF instead of classic JPEG/PNG often cuts file size by 30–70%. Serve the right size for different screen widths with srcset so mobile users do not download a desktop-sized image.
Caching: do not download the same thing twice
When a user returns to your site, re-downloading files that have not changed is pointless. The browser cache stores static resources on the user's device via the Cache-Control header:
location ~* \.(css|js|woff2|webp|avif)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
A one-year cache is safe because you add a hash to the filename when the content changes (e.g. app.4f8a2c.js). When the content changes, the name changes too, so the browser fetches the new file — this is called cache busting.
A CDN (such as Cloudflare, Fastly or BunnyCDN) moves this cache onto servers geographically close to the user, so content arrives fast regardless of physical distance. On the server side, you can cache repeated computations or database queries. In Laravel this is extremely simple:
$projects = Cache::remember('home.projects', 3600, function () {
return Project::orderBy('sort')->get();
});
Here the result is stored for an hour and the database is not hit on every request.
Shorten the critical path: resolve render blockers
The browser cannot paint the page until it has downloaded and processed the CSS and synchronous JavaScript inside the <head>; these are called render-blocking resources. A few practical measures:
- Inline the critical CSS needed for the first view (
<style>) and defer the rest. - Add
defer(orasyncif independent) to non-urgent scripts:<script src="app.js" defer></script> - Announce important resources early:
<link rel="preload" as="font" href="font.woff2" crossorigin> - Give web fonts
font-display: swap;so text stays visible while the font loads. - Review third-party scripts (analytics, chat widgets); each one can add a serious performance burden.
Frequently Asked Questions
What is a good page load time?
As a rule of thumb, the first meaningful content should appear in under 2.5 seconds (the LCP target), and full interactivity should be as low as possible. What matters is not a single magic number but keeping your Core Web Vitals within the "good" range.
Does lazy loading hurt SEO?
Done correctly, no. The native loading="lazy" attribute is well understood by search engines. But do not lazy-load the main above-the-fold image, and do not tie content entirely to JS until it is truly needed — otherwise crawlers may struggle to find your content.
Which should I do first: minify or caching?
They complement each other, but the fastest win usually starts with measuring. After that, image optimization and lazy loading give the biggest impact on most sites; minify and caching are durable, low-cost improvements. Applying them together is ideal.
Your site's speed is the first impression users get. If you start by measuring and apply lazy loading, minification and caching step by step, both the visitor experience and your search rankings improve noticeably. Want me to speed up your site with you? Get in touch and let's plan your performance audit.