Skip to main content

useSrcLoader Deep Dive

The useSrcLoader hook is a powerful utility for managing responsive images and CDN-specific URL generation. It centralizes the logic for creating optimized image sources across different screen sizes and providers.


Image CDN Loaders

Archibald supports a wide range of image CDNs out-of-the-box. The hook uses the global configuration to determine which transformation parameters (width, quality, fit, etc.) to append to the URL.

Supported providers include:

  • Akamai, AWS CloudFront, Cloudinary, Cloudflare
  • Contentful, Fastly, Gumlet, Imgix, Thumbor
  • And many others...
  • Vercel — targets Vercel's built-in image optimization (/_vercel/image), served from the deployment origin. Pair with app.image.target: 'proxy' when the media host is not publicly reachable (e.g. commerce behind Cloudflare Access) so the optimizer fetches through the media proxy.
  • Mock — a local/dev loader for pre-generated, size-variant static images. It rewrites the _<width>W token in the file name (foo_1400W.webpfoo_828W.webp) so the browser fetches the sized crop directly (no media endpoint/proxy), making responsive imgSizes visible without a real CDN. It is a no-op for URLs without such a token (e.g. /medias/?context=…). Set app.image.loader: 'Mock' per environment (e.g. environment/local.ts); do not use it in real environments.

Choosing the image target

app.image.target decides how loaders resolve the base URL, independent of which loader is selected:

  • direct — build absolute URLs from the configured protocol/host/port.
  • proxy — keep URLs relative so requests flow through the media proxy, even when a host is configured. Use this when the media backend sits behind access control the browser (or the Vercel optimizer) can't satisfy directly.
  • Unset — legacy implicit behavior: direct when host + protocol are set, otherwise relative.

Pass absolute: true to useSrcLoader when the consumer can't resolve relative URLs against a current origin — e.g. React Native's expo-image. The (possibly relative) loader result is then prefixed with the configured image origin. Leave it unset on the web, where relative URLs resolve against the page origin.

The provider is typically set in your archibald.config.ts:

// archibald.config.ts
export default {
images: {
loader: 'cloudinary'
}
}

Responsive Images (imgSizes)

The imgSizes parameter allows you to define multiple source sets based on media queries. This is essential for delivering the correctly sized image to different devices (mobile vs. desktop).

const { source, srcMedia } = useSrcLoader({
src: '/hero.jpg',
imgSizes: [
{ maxScreenWidth: 768, width: 400 }, // Mobile
{ minScreenWidth: 769, width: 1200 } // Desktop
]
});

Custom Loaders

If you need to use a provider not supported by default, or if you need custom logic for URL generation, you can provide a loader function.

const customLoader = ({ src, width, quality }) => {
return `https://my-custom-cdn.com/${src}?w=${width}&q=${quality}`;
};

const { source } = useSrcLoader({
src: 'image.jpg',
width: 800,
loader: customLoader
});

How it Works Step-by-Step

  1. Configuration Loading: The hook retrieves the global image configuration (provider, host, etc.).
  2. Base Source Generation: It calculates the "default" source URL using the provided src, width, and quality.
  3. Media Query Generation: For each entry in imgSizes:
    • It generates a standard CSS media query string (e.g., (max-width: 768px)).
    • It generates a specific URL for that size using either the custom loader or the default provider logic.
  4. Memoization: Both the primary source and the srcMedia array are memoized to prevent unnecessary recalculations during re-renders.
  5. Return: The hook returns the primary source (for the <img> tag) and the srcMedia array (for <source> tags within a <picture> element).

Best Practice: Always wrap your image in a <picture> element when using imgSizes to ensure the browser can pick the most optimal source based on the generated media queries.


Full Example

import { useSrcLoader } from '@archibald/client';

const MyComponent = () => {
// Image data to generate the src url in different sizes with
// current default/custom loader
const imageSizeData = [
{
maxScreenWidth: 1200,
minScreenWidth: 600,
width: 250,
quality: 100
},
{
maxScreenWidth: 599,
width: 150,
quality: 100
},
{
minScreenWidth: 1201,
src: '/image.png'
}
];

// Custom loader to generate src url
const customSrcLoader = ({ src, quality, width, config }) => {
return `<url>/${src}?q=${quality}&w=${width}`;
};

const imageData = {
src: '/image.png',
width: 100,
quality: 100,
imgSizes: imageSizeData,
loader: customSrcLoader
};

const { source, srcMedia } = useSrcLoader(imageData);

return (
<picture>
{srcMedia?.map((media, index) => (
<source key={index} media={media.media} srcSet={media.source} />
))}
<img src={source} alt="Example" />
</picture>
);
};

export default MyComponent;