Skip to main content

useSrcLoader

The useSrcLoader hook is used to dynamically generate and manage image sources and media queries based on provided parameters. It supports custom loaders for generating image URLs. More Info...

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

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

Parameters

NameTypeRequiredDescription
srcstring✔️
  • The source URL of the image.
widthnumber
  • The width of the image.
qualitynumber
  • The quality of the image.
imgSizesImageSize[]
  • An optional array of image size objects to generate source sets for different screen sizes.
loader(loader: CustomSrcLoader) => string
  • An optional custom loader function to generate image URLs.

ImageSize

PropertyTypeDescription
maxScreenWidthnumberMaximum screen width for the media query.
minScreenWidthnumberMinimum screen width for the media query.
srcstringSource URL for the image.
widthnumberWidth of the image.
qualitynumberQuality of the image.

CustomSrcLoader

PropertyTypeDescription
srcstringSource URL for the image.
widthnumberwidth of the image.
qualitynumberQuality of the image.

Return value

The hook returns an object containing:

The return type is SrcLoaderResult:

PropertyTypeDescription
sourcestring | undefinedThe generated source URL for the image.
srcMediaSourceMedia[] | undefinedAn array of source media objects containing media queries and source URLs. undefined when no imgSizes are passed.
headersRecord<string, string> | undefinedNative only. Request headers from app.image.headers.client that the client must send with the image request. undefined on web and when absolute is not set.

config

  • Type: DefaultImageApiConfig

The DefaultImageApiConfig objects have the following properties:

NameTypeDescription
basestringDefines base for request to the server. E.g. https://localhost:3100/<base>/v2/path
hoststringDefines host used in the request URL. E.g. https://<host>:3100/jsapi/v2/path
portstring | numberDefines port used in the request URL. E.g. https://localhost:<port>/jsapi/v2/path
protocolstringDefines protocol used in the request URL. E.g. <protocol>://localhost:3100/jsapi/v2/path
lazycustom | nativeDefines the default way of loading lazy images.
  • custom: Use javascrypt function to render the image when is visible in the screen.
  • Native: Use native loading of <img/> tag.
  • native is default value.
loaderloaderDefines the default CDN to generate the image Urls.
List of supported CDNs:
  • Akamai
  • AWSCloudFront
  • Cloudinary
  • Cloudflare
  • Contentful
  • Fastly
  • Gumlet
  • ImageEngine
  • Imgix
  • Thumbor
  • Sirv
  • SupaimageUrl
  • Supabase
  • Vercel
  • Mock
targetdirect | proxyDefines how loaders resolve the image base URL.
  • direct: build the URL from the configured protocol/host/port.
  • proxy: keep the URL relative so requests go through the media proxy, even when a host is configured.
  • Unset keeps the legacy implicit behavior (direct when host + protocol are set, otherwise relative).

The Vercel loader

Vercel targets Vercel's built-in image optimization endpoint, generating /_vercel/image?url=…&w=…&q=… URLs served from the deployment origin. Because the optimizer runs on the deployment itself, pair it with target: 'proxy' when the underlying media host is not publicly reachable (e.g. commerce behind Cloudflare Access) so the optimizer fetches the source through the media proxy. For direct-host serving, add the host to the Vercel build output's images.remotePatterns/domains (configurable via project.vercel.config in archibald.json).

The Mock loader

Mock is a local/dev loader for pre-generated, size-variant static images. It rewrites a _<width>W size token in the file name so the browser fetches the correctly-sized asset directly from where it is served — no image endpoint, no proxy — making responsive imgSizes (e.g. the CMS banners) actually differ per breakpoint in local/dev, where no real image CDN is configured. Set it per environment, e.g. in environment/local.ts:

app: {
image: {
loader: 'Mock'
}
}

/public/Electronics_EN_02_1400W.webp at width 828/public/Electronics_EN_02_828W.webp (the _02 segment is untouched — only the _<width>W token is rewritten). It is a deliberate no-op for URLs without a _<width>W.<ext> token (e.g. /medias/?context=… product images are returned unchanged, so no ?width= is ever appended). Provide the matching sized files alongside the base image. Do not use it outside local/dev — real environments should configure a real CDN loader.


Practical Code Example

In application code you normally do not call this hook directly — use the Image atom (shop/client/components/atoms/image/Image), which wraps useSrcLoader and additionally handles lazy loading, placeholders, aspect-ratio reservation and LCP preloading. Pass it imgSizes and it renders the <picture> for you:

// shop/client/features/cms/components/banners/CMSBannersComponent.tsx
// One breakpoint per source, non-overlapping, so every viewport is matched by exactly one <source>.
const BANNER_IMAGE_SIZES = [
{ maxScreenWidth: 767, width: 828 },
{ minScreenWidth: 768, maxScreenWidth: 1199, width: 1200 },
{ minScreenWidth: 1200, width: 1400 }
];

<Image src={banner.media.url} alt={banner.media.altText} imgSizes={BANNER_IMAGE_SIZES} isLCP={isAboveTheFold} />;

Call the hook yourself when you need the URLs outside an <img> — a CSS background-image, a canvas, a preload hint. This is the <picture> markup the Image atom builds from the hook's output:

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

export function ResponsiveBanner({ src }: { src: string }) {
const { source, srcMedia } = useSrcLoader({
src,
width: 1400,
imgSizes: BANNER_IMAGE_SIZES
});

if (!srcMedia?.length) {
return <img src={source} alt="" />;
}

return (
<picture>
{/* The browser takes the first <source> whose media query matches. */}
{srcMedia.map(({ media, source: mediaSource }, index) => (
<source key={`${mediaSource}-${index}`} media={media} srcSet={mediaSource} />
))}
{/* Fallback for browsers without <picture> and for viewports no query matched. */}
<img src={source} alt="" />
</picture>
);
}

Note that width is passed at the top level as well: source is generated from the top-level parameters only, so without it the <img> fallback is built with no width at all while the <source> candidates are sized.

note

Whether the three candidates actually differ in bytes is decided by the configured app.image.loader. With the Mock loader described above, src must carry a _<width>W token (e.g. /public/Electronics_EN_02_1400W.webp) for the rewrite to happen — for any other URL the loader is a deliberate no-op and all three sources resolve to the same file.