Image Component
See original GitHub issueNext has this actually useful Image component which wraps the img tag to optimize how you use it and enforce good practices like providing a width and height to avoid layout shifts.
Remix used to have this img: prefix on the imports to get an object instead of a string and that object contained data like the width, height, srcset, placeholder, etc. based on query params. This was removed on the migration to esbuild.
If it’s hard to add that way to import adding the component could be a good fallback to have a way to optimize image load.
Component Interface
The component should be used as a drop-in replacement of the img tag, like Form with form.
// Switch from this
<img src={url} alt="something useful here" width={500} height={500} />
// To this
<Image src={url} alt="something useful here" width={500} height={500} />
And just with that it should be enough to start getting the benefit. Other options could be:
interface ImageProps extends HTMLImageAttributes { // it should still support normal img attributes
  src: string;
  width: number; // required
  height: number; // required
  alt: string; // should probably be required
  loader?(options: { src: string; width: number; quality: number }): string;
  quality?: string; // range from 0 to 100
  placeholder?: string; // if defined the string should be used as placeholder, if not it should be empty while the image loads
}
The loader should also be configured in the remix.config file so you don’t need to add it individually. Remix could come with some built-in image loaders for services like Cloudinary, Cloudflare Image Resizing (when creating a new project with Cloudflare adapter this could come as the default) and maybe a custom one with some hidden endpoint created by Remix.
Special import
If adding back the support to img: imports, or using assert { type: "image" } in a future, is possible the object returned by the import could come with the same interface the Image component expects, that way you can use it like this:
import guitar from "img:~/guitar.jpg?quality=80&srcset=720,1080,2048&placeholder";
// with import assertion
import guitar2 from "~/guitar.jpg?quality=80&srcset=720,1080,2048&placeholder" assert { type: "image" };
export default function Route() {
  // super simple usage
  return (
    <>
      <Image {...guitar} />
      <Image {...guitar2} />
    </>
  );
}
In this case the usage will be simplified a lot, you import and pass the imported to the component and it should magically work.
Issue Analytics
- State:
 - Created 2 years ago
 - Reactions:18
 - Comments:17 (7 by maintainers)
 

Top Related StackOverflow Question
@ryanflorence any news on this?
Thanks for your great work!
@sergiodxa yeah that was the plan when we had the image importer. Always thinking on the same wavelength!
We’re not sure that the compiler is the right place to process something as expensive as images so we decided to remove it and put it on the backburner until v1 is humming along. We have some rough ideas about how to help out with images w/o making the compiler do it. I hope we can get to sooner than later!