Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add <Image> component #65

Open
lifeiscontent opened this issue Nov 9, 2023 · 0 comments
Open

Add <Image> component #65

lifeiscontent opened this issue Nov 9, 2023 · 0 comments

Comments

@lifeiscontent
Copy link

lifeiscontent commented Nov 9, 2023

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);
}
@TooTallNate TooTallNate changed the title Add Image component for remix Add <Image> component Mar 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant