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
| Name | Type | Required | Description |
|---|---|---|---|
| src | string | ✔️ |
|
| width | number |
| |
| quality | number |
| |
| imgSizes | ImageSize[] |
| |
| loader | (loader: CustomSrcLoader) => string |
|
ImageSize
| Property | Type | Description |
|---|---|---|
| maxScreenWidth | number | Maximum screen width for the media query. |
| minScreenWidth | number | Minimum screen width for the media query. |
| src | string | Source URL for the image. |
| width | number | Width of the image. |
| quality | number | Quality of the image. |
CustomSrcLoader
| Property | Type | Description |
|---|---|---|
| src | string | Source URL for the image. |
| width | number | width of the image. |
| quality | number | Quality of the image. |
Return value
The hook returns an object containing:
The return type is SrcLoaderResult:
| Property | Type | Description |
|---|---|---|
| source | string | undefined | The generated source URL for the image. |
| srcMedia | SourceMedia[] | undefined | An array of source media objects containing media queries and source URLs. undefined when no imgSizes are passed. |
| headers | Record<string, string> | undefined | Native 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:
| Name | Type | Description |
|---|---|---|
| base | string | Defines base for request to the server. E.g. https://localhost:3100/<base>/v2/path |
| host | string | Defines host used in the request URL. E.g. https://<host>:3100/jsapi/v2/path |
| port | string | number | Defines port used in the request URL. E.g. https://localhost:<port>/jsapi/v2/path |
| protocol | string | Defines protocol used in the request URL. E.g. <protocol>://localhost:3100/jsapi/v2/path |
| lazy | custom | native | Defines the default way of loading lazy images.
|
| loader | loader | Defines the default CDN to generate the image Urls. List of supported CDNs:
|
| target | direct | proxy | Defines how loaders resolve the image base URL.
|
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.
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.