Skip to content
Twilight React Playground
ثيم رائدaren

getCdnImageUrl, getCdnImageSrcSet

functionBeginnerserverbrowserlive demo

Rewrite a Salla CDN image URL into a resized copy, or into a srcset of several widths, so pictures download faster.

import { getCdnImageUrl, getCdnImageSrcSet, CdnImageOptions } from '@salla.sa/twilight-theme-engine/utils/cdn-image';

In plain words

Product and category photos from the Salla API are full-size files at addresses like https://cdn.salla.sa/…/photo.jpg. Salla's CDN (the network of servers that delivers those files) can send a smaller copy when the address asks for one.

getCdnImageUrl(url, { width: 400 }) returns that address. getCdnImageSrcSet(url, [320, 640]) returns a value for the srcset attribute, so the browser picks the size that fits the screen.

Both only build text: nothing is downloaded until an <img> uses the result. The engine's Image component calls them for you.

Signature

function getCdnImageUrl(url: string | undefined, options?: CdnImageOptions): string | undefined

function getCdnImageSrcSet(
  url: string | undefined,
  widths: readonly number[],
  options?: Omit<CdnImageOptions, 'width' | 'height'>
): string | undefined

interface CdnImageOptions {
  width?: number | string;
  height?: number | string;
  quality?: number;
}

Try it live

Both helpers rewrite a Salla CDN image URL into a resized copy. The image below is downloaded from the URL they return.Try this: lower the width and watch the file size shrink, then pick the flag: its host is not a Salla CDN, so nothing changes and the srcset is undefined.
Storefront canvas · ar · RTL
getCdnImageUrl(url, options)
https://cdn.salla.sa/cdn-cgi/image/fit=scale-down,onerror=redirect,format=auto,width=200/mQgZlG/FaWuBveWH22EqE2qUX9gbUVfG3dVO7vzTyNPBaGf.jpg
getCdnImageSrcSet(url, widths)
https://cdn.salla.sa/cdn-cgi/image/fit=scale-down,onerror=redirect,format=auto,width=320/mQgZlG/FaWuBveWH22EqE2qUX9gbUVfG3dVO7vzTyNPBaGf.jpg 320w, https://cdn.salla.sa/cdn-cgi/image/fit=scale-down,onerror=redirect,format=auto,width=640/mQgZlG/FaWuBveWH22EqE2qUX9gbUVfG3dVO7vzTyNPBaGf.jpg 640w, https://cdn.salla.sa/cdn-cgi/image/fit=scale-down,onerror=redirect,format=auto,width=960/mQgZlG/FaWuBveWH22EqE2qUX9gbUVfG3dVO7vzTyNPBaGf.jpg 960w
Controls
0 means not set.
0 means not set.
0 means not set.
What a theme writes
import { getCdnImageSrcSet, getCdnImageUrl } from '@salla.sa/twilight-theme-engine/utils/cdn-image';

const url = 'https://cdn.salla.sa/mQgZlG/FaWuBveWH22EqE2qUX9gbUVfG3dVO7vzTyNPBaGf.jpg';

export function ProductPhoto({ alt }: { alt: string }) {
  return (
    <img
      src={getCdnImageUrl(url, { width: 200 })}
      srcSet={getCdnImageSrcSet(url, [320, 640, 960])}
      sizes="(max-width: 640px) 100vw, 400px"
      alt={alt}
    />
  );
}

Example

app/components/product/ProductThumb.tsx
import { getCdnImageSrcSet, getCdnImageUrl } from '@salla.sa/twilight-theme-engine/utils/cdn-image';
import type { Product } from '@salla.sa/twilight-theme-engine/types';

export function ProductThumb({ product }: { product: Product }) {
  const url = product.image?.url;
  return (
    <img
      src={getCdnImageUrl(url, { width: 300 })}
      srcSet={getCdnImageSrcSet(url, [150, 300, 600])}
      sizes="(max-width: 640px) 50vw, 300px"
      alt={product.image?.alt ?? product.name}
      loading="lazy"
    />
  );
}

How it behaves

  • Only URLs on cdn.salla.sa, cdn.salla.network and cdn.files.salla.network are rewritten. Any other URL, cdn.assets.salla.network included, comes back unchanged.

  • The result is https://<host>/cdn-cgi/image/[quality=Q,]fit=scale-down,onerror=redirect,format=auto[,width=W][,height=H]/<path>. A transform already in the URL is removed first; the query string is kept.

  • fit=scale-down fits the image inside the box and never enlarges it. Checked against the demo store: a 500×500 photo asked for width=200,height=100 arrives as 100×100, and asked for width=3000 arrives as 500×500. format=auto lets the CDN send a lighter format the browser supports; onerror=redirect falls back to the original.

  • width and height may be strings; they go through Number(), and 0, "" or "0" count as not set. quality is added whenever it is not null or undefined.

  • getCdnImageSrcSet returns "<url> 150w, <url> 300w, …", one candidate per width. Pass sizes too, or the browser assumes the image is as wide as the screen.

  • Pure string functions with no store or window: the same result on the server and in the browser, in components, head() functions and loaders. This subpath also loads in plain Node.

Gotchas

  • With neither width nor height, getCdnImageUrl returns the URL unchanged, even when quality is set.

  • getCdnImageSrcSet is all or nothing: it returns undefined when widths is empty or when the URL cannot be rewritten (another host, a relative path). srcSet={undefined} renders no attribute, so the browser uses src.

  • A relative path such as images/hero.jpg is not a URL and comes back unchanged. For files on the asset CDN use cdn(path, width) from @salla.sa/twilight-theme-engine/utils.

Related

Source and docs