remix
remix copied to clipboard
Add `<Image>` component
Since Vercel supports image optimization out of the box, it would be really great to see a progressively enhanced image component for remix that uses Vercel's image optimization, and falls back to the default source URL in development
here's a rough proof of concept:
app/components/image.tsx
export function Image({
src,
width,
loading = "lazy",
...props
}: Omit<React.ComponentPropsWithoutRef<"img">, "src" | "width"> &
Required<Pick<React.ComponentPropsWithoutRef<"img">, "src" | "width">>) {
return (
// eslint-disable-next-line jsx-a11y/alt-text
<img
{...props}
src={imageSrc(src, width)}
loading={loading}
width={width}
/>
);
}
export function imageSrc(src: string, width: number | string, q = 75) {
return `/resources/image?url=${encodeURIComponent(src)}&w=${width}&q=${q}`;
}
export function imageSrcSet(src: string, width: number, q = 75) {
return `${imageSrc(src, width, q)}, ${imageSrc(
src,
width * 1.5,
q
)} 1.5x, ${imageSrc(src, width * 2, q)} 2x`;
}
app/routes/resources.image.tsx
import type { DataFunctionArgs } from "@remix-run/node";
function getAbsoluteURL(request: Request, url: string) {
if (url.startsWith("http:") || url.startsWith("https:")) {
return new URL(url).toString();
}
let host =
request.headers.get("X-Forwarded-Host") ??
request.headers.get("host") ??
new URL(request.url).host;
let protocol = host.includes("localhost") ? "http" : "https";
if (url.startsWith("/")) {
return new URL(url, `${protocol}://${host}`).toString();
}
return new URL(`${protocol}//${url}`).toString();
}
export function loader({ request }: DataFunctionArgs) {
const url = new URL(request.url);
const src = url.searchParams.get("url")!;
const vercelUrl = "/_vercel/image" + url.search;
const destination = process.env.VERCEL
? getAbsoluteURL(request, vercelUrl)
: getAbsoluteURL(request, src);
return fetch(destination);
}