Most WordPress speed advice starts with "install an optimization plugin". That's step three. Steps one and two produce bigger gains and cost nothing.

Step 1: Upload Discipline

The single most effective change:

  • Resize before uploading: 1600 px on the long edge for content images, 1920 px for full-width heroes. Camera originals at 4000+ px serve no purpose on a website.
  • Compress before uploading to a sensible target (60–150 KB for content images).
  • Choose the right format: JPEG/WebP for photos, PNG only for transparency and flat graphics, SVG for logos and icons where your setup allows it safely.
  • Name files descriptively before upload — the filename becomes part of the URL permanently.

A plugin compressing a 6 MB upload is fixing a problem you created seconds earlier. Fixing it upstream also stops WordPress generating fifteen oversized derivatives.

Step 2: Check What the Theme Actually Requests

Open a page, inspect the largest image and compare its intrinsic size to its rendered size. If a 2048 px file renders at 640 px, your theme is requesting the wrong registered size. This is the most common WordPress performance bug and no plugin can fix it — it's a template decision.

While you're there:

  • Confirm the hero image is not lazy-loaded.
  • Confirm width and height attributes are present (WordPress adds them, but page builders sometimes strip them).
  • Look for images loaded via CSS backgrounds in a page builder — they're invisible to the preload scanner.

Step 3: Then Use a Plugin, for the Right Things

Good optimization plugins do three useful jobs:

  • Convert to WebP/AVIF and serve them with fallbacks.
  • Bulk-compress the existing library — valuable precisely because past uploads were undisciplined.
  • Regenerate or clean up unused registered sizes after a theme change.

Be aware that some plugins re-compress already-compressed images every time settings change, stacking artifacts. Compress once, well.

Step 4: Delivery

  • A CDN in front of the site helps more than any plugin setting for a geographically spread audience.
  • Cache aggressively: images are immutable in practice; long max-age with versioned filenames is safe.
  • Enable lazy-loading below the fold (native in WordPress) but exclude the hero and anything in the first viewport.

Step 5: Verify

Run Lighthouse before and after, and check the specific diagnostics: "Properly size images", "Serve images in next-gen formats", "Efficiently encode images", "Largest Contentful Paint element". Then confirm with field data over the following weeks, because lab scores on your machine don't reflect a phone on mobile data.

If a change doesn't move those numbers, it isn't an optimization — it's a setting you changed.