brisa-build / brisa

The Web Platform Framework.
https://brisa.build
MIT License
451 stars 12 forks source link

support to crop/resize images in build-time #522

Open losnappas opened 1 month ago

losnappas commented 1 month ago

There is a cool feature in Next.js, basically makes images responsive by putting in a srcset etc. attributes. Nextjs had a separate image compression "server endpoint" last I checked, however personally I think creating a couple of resized images for the srcset, during build, is good enough.

Any thoughts on supporting such a feature?

aralroca commented 1 month ago

Thank you, @losnappas, for the proposal. I have added it to the 1.0 route map, and we will discuss its implementation here.

instead of making a Server Component (in Brisa <Image /> is a Server Component), I would make something that can also be used inside the Web Components without using slots/children.

If all we want is the crop/resize action, we could support it with:

<img src="..." width="500" height="500" cropImage />

Since the srcset already exists with the native element, we can add this attribute extension so that at build time, a Bun macro will do this job. (similar than renderOn="build").

The name of this attribute, or a better way to do it, remains open. But it would prevent it from being a Server Component for use anywhere.

aralroca commented 1 month ago

surely as a result we could put the suffix of the hash of the image in case an image is cut in different places.

/my-image -> /my-image-empdnk6q.jpeg

Or add the size:

/my-image -> /my-image-500x500.jpeg

AlbertSabate commented 1 month ago

This would be a very nice to have yeah. It would be nice if we can choose between:

Thinking further, maybe this would be a nice idea for a Brisa plugin or part of a cloud adapter, instead of having it on Brisa core ??

aralroca commented 1 month ago
  • cropImage or resizeImage, if we crop de image, what would it be the strategy?

maybe something like that?

<img 
  src="..." 
  width={500} 
  height={500} 
  optimize={{ 
    strategy: 'crop',  // Strategy can be 'crop', 'resize' or 'none'
    quality: 50,       // Compression quality (1-100)
    ext: 'avif'        // Output format, e.g., 'avif', 'webp', 'jpeg', 'png'
  }} 
/>

Although we should do that we can do in all operating systems. It is necessary to test the Bun tool to run C in runtime, this way it could be put in a macro to use it in build-time, and use C without pre-compiled and it adapts according to the OS just at the moment. It is necessary to test it...

Thinking further, maybe this would be a nice idea for a Brisa plugin or part of a cloud adapter, instead of having it on Brisa core ??

The good thing about doing it in build-time (in prod only) is that it would work on all Cloud Providers.

AlbertSabate commented 1 month ago

Sounds good. Missing width || height || srcset. srcset generate defined sizes. props.optimize === undefined => no optimisations by Brisa ??

aralroca commented 1 month ago

Exactly. However, we need to take into account how to handle these cases:

<picture>
  <source media="(prefers-color-scheme: dark)" srcSet={dark} />
  <source media="(prefers-color-scheme: light)" srcSet={light} />
  <img {...imgProps} />
</picture>

Apart from the picture and source that should also be managed, only if the src or srcSet is dynamic, it will be difficult to manage it in this way that we have proposed in build-time. Perhaps it is better to look for an alternative. I don't know how <Image /> of Next.js is managed when the src is a dynamic value and not static, it would be necessary to look at how it is done to inspire us, or to look for a better way.

AlbertSabate commented 1 month ago

NextJS for dynamic src is using Vercel image optimization https://vercel.com/docs/image-optimization which relies on the cloud provider. In my opinion Brisa should handle the statics, and enable to integrate cloud optimizers somehow. Being up to the user how to use it. Some devs may want to use a self hosted image service also...

aralroca commented 1 month ago

Ok, now I understand what you meant before.

Of course, here each Cloud Provider will have its own way of managing it: Cloudflare, Netlify, Vercel, etc...

For Brisa's part, using a Proxy to handle this puts too much load on the CPU. Besides that doing a resize in build-time makes sense to load the images faster, but if it is done in a runtime with a proxy I don't see the benefit, since it will take several milliseconds to do this optimization. That said, I would avoid having a proxy, as the images are always already in /public after the build.

aralroca commented 1 month ago

Astro implementation for Vercel adapter: https://github.com/withastro/adapters/tree/main/packages/vercel/src/image