← Images / images / optimization / transformations
Transformace přes fetch
Workers vám umožňuje optimalizovat obrázky pomocí vlastního schématu URL adres.
Parametry optimalizace obrázků můžete nastavit na fetch() dílčí požadavek ve Workeru pomocí cf.image Jde o stejný podkladový mechanismus jako u Rozhraní URL, ale zároveň vám dává programovou kontrolu nad každým požadavkem na obrázek.
Chcete-li pracovat přímo s bajty obrázku místo s URL adresami, použijte Vazba Images binding.
Zde je několik příkladů flexibility, kterou vám Workers nabízí:
- Použít vlastní schéma URL. Místo zadávání rozměrů v pixelech v URL obrázků použijte předdefinované názvy, například
thumbnailalarge. - Skrytí skutečného umístění původního obrázku. Obrázky můžete ukládat do externího S3 bucketu nebo do skryté složky na serveru, aniž by tato informace byla vidět v URL.
- Implementace vyjednávání obsahu. To se hodí k dynamickému přizpůsobení velikosti, formátu a kvality obrázků podle zařízení a stavu sítě.
Jak to funguje
K funkci změny velikosti se přistupuje přes options z fetch() subrequest uvnitř Workeru. fetch() funkce přijímá parametry ve druhém argumentu uvnitř {cf: {image: {…}}} objekt.
Ve vašem workeru, kde byste obrázek načítali pomocí fetch(request), přidejte možnosti jako v následujícím příkladu:
fetch(imageURL, {
cf: {
image: {
fit: "scale-down",
width: 800,
height: 600,
},
},
});Tyto typy jsou k dispozici také v naše knihovna typových definic TypeScriptu pro Workers ↗.
cf.image je k dispozici na jakékoli zóně, která hostuje Worker, včetně *.workers.dev subdomén. Každá transformace se účtuje účtu, kterému Worker patří.
Konfigurace Workeru
Vytvořte nový skript v sekci Workers v Cloudflare dashboardu. Omezte skript Workeru na cestu určenou k poskytování assetů, například /images/* nebo /assets/*. Změnit velikost lze pouze u podporovaných formátů obrázků. Pokus o změnu velikosti jiného typu zdroje (CSS, HTML) skončí chybou.
Cestu zpracovávanou Workerem je nejlepší oddělit od cesty k původním (nezměněným) obrázkům, aby nedocházelo ke smyčkám požadavků způsobeným tím, že worker pro změnu velikosti obrázků volá sám sebe. Obrázky můžete uložit například do example.com/originals/ adresáře a změnu velikosti řešit pomocí example.com/thumbnails/* cesta, která načítá obrázky z /originals/ adresáře. Pokud jsou zdrojové obrázky uloženy na místě, které obsluhuje Worker, musíte zabránit tomu, aby Worker vytvořil nekonečnou smyčku.
Prevence smyček požadavků
Aby mohl Worker provádět změnu velikosti a optimalizace, musí mít možnost načíst původní, nezmenšený obrázek z vašeho origin serveru. Pokud se cesta, kterou Worker zpracovává, překrývá s cestou, na níž jsou obrázky uloženy na vašem serveru, může tím vzniknout nekonečná smyčka, kdy si Worker sám od sebe vyžaduje obrázky.
Musíte rozpoznat, které požadavky mají směřovat přímo na origin server. Pokud je image-resizing řetězec je přítomen v Via hlavička, znamená to, že jde o požadavek z jiného Workeru, a měl by být směrován na origin server:
export default {
async fetch(request) {
// If this request is coming from image resizing worker,
// avoid causing an infinite loop by resizing it again:
if (/image-resizing/.test(request.headers.get("via"))) {
return fetch(request);
}
// Now you can safely use image resizing here
},
};Chybějící náhled v dashboardu
Náhled skriptu v editoru Workeru ignoruje fetch() a vždy načte obrázky beze změny velikosti. Chcete-li vidět efekt transformací obrázků, musíte skript Workeru nasadit a použít mimo editor.
Lokální vývoj
Při spuštění wrangler dev, cf.image transformace se aplikují lokálně pomocí zjednodušené simulace s nízkou věrností.
Podporována je pouze část možností, mimo jiné resize, rotate, format a background colour. Nepodporované možnosti se ignorují.
Zpracování chyb
Pokud nelze změnit velikost obrázku, například proto, že obrázek neexistuje nebo byly parametry změny velikosti neplatné, bude mít odpověď HTTP stav označující chybu (například 400, 404, nebo 502).
Ve výchozím nastavení se chyba přepošle do prohlížeče, ale způsob zpracování chyb můžete určit sami. Prohlížeč můžete například místo toho přesměrovat na původní obrázek beze změny velikosti:
const response = await fetch(imageURL, options);
if (response.ok || response.redirected) {
// fetch() may respond with status 304
return response;
} else {
return Response.redirect(imageURL, 307);
}Pokud jsou původní obrázky na vašem serveru velmi velké, může být lepší chybějící obrázky vůbec nezobrazovat, než použít jako záložní řešení příliš velké obrázky, které by mohly spotřebovat příliš mnoho šířky pásma či paměti nebo narušit rozvržení stránky.
Obrázky, jejichž načtení selhalo, můžete také nahradit záložním obrázkem:
const response = await fetch(imageURL, options);
if (response.ok || response.redirected) {
return response;
} else {
// Change to a URL on your server
return fetch("https://img.example.com/blank-placeholder.png");
}Příklad workeru
Za předpokladu, že nastavit Worker na https://example.com/image-resizing ke zpracování URL, jako je https://example.com/image-resizing?width=80&image=https://example.com/uploads/avatar1.jpg:
/**
* Fetch and log a request
* @param {Request} request
*/
export default {
async fetch(request) {
// Parse request URL to get access to query string
let url = new URL(request.url);
// Cloudflare-specific options are in the cf object.
let options = { cf: { image: {} } };
// Copy parameters from query string to request options.
// You can implement various different parameters here.
if (url.searchParams.has("fit"))
options.cf.image.fit = url.searchParams.get("fit");
if (url.searchParams.has("width"))
options.cf.image.width = parseInt(url.searchParams.get("width"), 10);
if (url.searchParams.has("height"))
options.cf.image.height = parseInt(url.searchParams.get("height"), 10);
if (url.searchParams.has("quality"))
options.cf.image.quality = parseInt(url.searchParams.get("quality"), 10);
// Your Worker is responsible for automatic format negotiation. Check the Accept header.
const accept = request.headers.get("Accept");
if (/image\/avif/.test(accept)) {
options.cf.image.format = "avif";
} else if (/image\/webp/.test(accept)) {
options.cf.image.format = "webp";
}
// Get URL of the original (full size) image to resize.
// You could adjust the URL here, e.g., prefix it with a fixed address of your server,
// so that user-visible URLs are shorter and cleaner.
const imageURL = url.searchParams.get("image");
if (!imageURL)
return new Response('Missing "image" value', { status: 400 });
try {
// TODO: Customize validation logic
const { hostname, pathname } = new URL(imageURL);
// Optionally, only allow URLs with JPEG, PNG, GIF, or WebP file extensions
// @see https://developers.cloudflare.com/images/url-format#supported-formats-and-limitations
if (!/\.(jpe?g|png|gif|webp)$/i.test(pathname)) {
return new Response("Disallowed file extension", { status: 400 });
}
// Demo: Only accept "example.com" images
if (hostname !== "example.com") {
return new Response('Must use "example.com" source images', {
status: 403,
});
}
} catch (err) {
return new Response('Invalid "image" value', { status: 400 });
}
// Build a request that passes through request headers
const imageRequest = new Request(imageURL, {
headers: request.headers,
});
// Returning fetch() with resizing options will pass through response with the resized image.
return fetch(imageRequest, options);
},
};Při testování změny velikosti obrázků nejprve nasaďte skript. V online editoru v dashboardu totiž změna velikosti nefunguje.
Upozornění na cacheKey
Obrázky se změněnou velikostí se vždy ukládají do mezipaměti. Ukládají se jako další varianty pod záznamem mezipaměti pro URL adresu zdrojového obrázku v plné velikosti v fetch dílčí požadavek. Nemusíte se obávat používání mnoha různých Workerů nebo mnoha externích URL, tyto skutečnosti neovlivňují cachování zmenšených obrázků a pro jejich správné cachování nemusíte nic dělat.
Pokud používáte cacheKey fetch, kterou sjednotíte mezipaměti více zdrojových adres URL, nezahrnujte žádné možnosti změny velikosti do cacheKey. Tím dojde k fragmentaci cache a zhoršení výkonu cachování. Parametr cacheKey by měla odkazovat pouze na URL zdrojového obrázku v plné velikosti, nikoli na žádnou z jeho zmenšených verzí.