Diagnosing Astro Image Optimization Failures When srcset Is Missing in Production
A practical diagnostic guide for Astro sites where production builds serve raw images without srcset, featuring a cause table, ordered checks, and fixes.
20 Jun 2026, 09:23 UTC

The recognizable condition
You deploy an Astro site and images load, but they are raw files. In the built HTML, the <img> tags point to the original source path or to unprocessed assets, there is no srcset, no width/height hints, and file sizes in the dist folder match the source. While this is expected in development mode, in production it indicates the image optimization service was not invoked.
Useful takeaway: Astro only applies image optimization during a production build and only when the <Image> component is used with a supported loader and configuration. If any link in that chain is broken, Astro falls back to serving raw assets.
Cause and diagnostic table
| Symptom | Likely cause | Quick check |
|---|---|---|
| Images served as raw files, no srcset | Missing or inactive image plugin/service | Build log has no image conversion messages; dist contains original filenames |
<img> used instead of <Image> | Incorrect import syntax | Source uses <img src="..."> not the Astro Image component |
| Only some images optimized | Unsupported path or file type | Images outside src/ or non-JPEG/PNG/WebP/AVIF |
| Optimization works locally but not on host | Stale build cache or CDN serving origin | dist/assets contains optimized files but browser requests origin URLs |
| No optimization in CI/CD | NODE_ENV not set to production | Build script runs without production environment variables |
Ordered checks
Confirm you are inspecting a production build. Run the following in the project root with write permissions to
dist:npm run buildDev mode serves raw assets by design to maintain speed. Risk: This command overwrites the
distfolder. Expected check: Opendist/index.htmland look for URLs under/_astro/and reduced file sizes indist/assets.Verify the Image component is used. Open the page component and check the imports. The correct implementation requires the
astro:assetsmodule:import { Image } from 'astro:assets';Expected check: Markup must use
<Image src={...} alt="..." />. If a plain<img>tag is used, the optimization service is bypassed entirely.Check astro.config.mjs for image configuration. Inspect
astro.config.mjsin the project root. A defined image block enables the necessary service hooks.// astro.config.mjs export default { image: { // service entry point and limits as needed } }Risk: Changing the configuration invalidates previous builds and requires a fresh deployment.
Validate dependencies and loader. The image service requires a supported loader such as
sharp. Ensure it is listed inpackage.json. Run in the project root:npm list sharpExpected check: The package must be present. Without a valid loader, the build process typically falls back to raw copies of the assets.
Confirm source paths and formats. Images must be imported from within the project source (typically
src/assets). Remote URLs or files located in thepublic/folder are not processed by the optimization pipeline. Supported formats include JPEG, PNG, WebP, and AVIF.Clear stale build artifacts. Remove the
distand.astrocache directories, then rebuild.rm -rf dist .astroRisk: This deletes all generated assets. Expected check: A new build should generate fresh
/_astro/hashed URLs.Check environment variables. Ensure the build runs with the production environment set.
NODE_ENV=production npm run buildCertain optimizations are skipped if
NODE_ENVis not explicitly set to production during the build process.
Fixes tied to findings
Missing service or configuration
Add the image configuration to astro.config.mjs and install the sharp dependency. Clear the dist folder and rebuild the site.
Wrong component usage
Replace plain <img> tags with the Astro Image component and import the image as a module rather than a string path:
import heroImage from '../assets/hero.jpg';
<Image src={heroImage} alt="Hero Image" widths={[640, 1024]} />The src attribute must resolve to a local import object to trigger the optimization pipeline.
Unsupported file or path
Move images from the public/ directory into src/assets/. Convert any unsupported image formats to JPEG, PNG, or WebP before importing them into the component.
Stale cache or CDN
Purge the build cache and the CDN cache after a successful production build. Verify the fix by requesting a fresh asset URL and checking the Content-Type and file size in the browser network tab.
Limitations and verification
Image optimization is only applied during production builds; the development server intentionally serves raw assets to reduce startup time. Be aware that very large image directories can significantly increase build times; consider using lazy loading or selective optimization for high-volume galleries.
Practical verification:
- Open the built HTML in
distand confirm<img>tags reference/_astro/URLs and include asrcsetattribute. - Compare the file sizes between the original source images and the resulting files in
dist/assets. - Review build logs for confirmation messages from the image service indicating successful conversion.
Escalation criteria
Escalate the issue to senior engineering or Astro support when:
- Configuration is correct, dependencies are present, and the production build succeeds, yet images remain unoptimized in
dist. - Build logs show loader crashes or memory errors during the image processing phase.
- Optimization works consistently in local production builds but fails in CI/CD environments despite identical configurations.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.