-
Notifications
You must be signed in to change notification settings - Fork 29.7k
RFC: Image Optimization #17141
-
Goals
Non-Goals
Background#16832 is introducing the Image component that allows for a bunch of optimizations to be handled like lazy-loading and ProposalThe image optimization will seamlessly integrate with This endpoint will be under
The endpoint will automatically serve the best format (e.g. accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8 Example: Note that you'd generally not construct the url in this way as you'd be using the To avoid abuse the user has to provide a list of supported image widths to avoid enumeration attacks: // next.config.js module.exports = { images: { // This setting would be defaulted to commonly known device sizes to ensure the srcset can be generated for next/image. It can optionally be overwritten to a custom setting. // sizes: [1024, 2000] } } Support for external imagesImages on a web page are generally a blend of local images as part of the project and external images that come from an external data source. The image optimization will support both local images and external images. In case of external images you'll need to add the domains (or domain pattern) to an allow list. This is to ensure that malicious users can't hijack the image optimization for their own use: // next.config.js module.exports = { images: { domains: ['cms.example.com', 'example.com'] } } Install TimeThe When looking at https://squoosh.app/ we (@Timer and me) noticed that it ships WebAssembly files for the image optimization. Furthermore these files are really small (a couple hundred kB) compared to the existing image optimization libraries on npm and do not have native dependencies. Seemingly these files are a great candidate to solve the install time issue. They're located here: https://github.com/GoogleChromeLabs/squoosh/tree/dev/codecs Upon further investigation we found that @cyrilwanner has ported these codes to npm libraries in this repository: https://github.com/cyrilwanner/wasm-codecs potentially we can use/reuse parts of this. The ideal outcome would probably be having these files published to npm from the squoosh repository so they're always up to date. Upon even further investigation with help from @cyrilwanner who did a performance comparison of the webassembly version against Cyril's comparison of image solutionsPerformance comparison Hardware JPEG Tiny image (6.3KB)
Small image (166.0KB)
Medium image (603.8KB)
Large image (2211.2KB)
PNG Tiny image (17.0KB)
Small image (139.4KB)
Medium image (538.7KB)
Large image (1949.6KB)
Currently the install size of Overall having looked into all these options it seems that eventually using However, for the time being we can make |
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 115 -
🎉 51 -
❤️ 61 -
🚀 46 -
👀 24
Replies: 17 comments 12 replies
-
Finally 🚀.
Can’t wait to get that 100 lighthouse performance scores once again 😋
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 13
-
yay
Beta Was this translation helpful? Give feedback.
All reactions
-
Wow, this is fantastic!!!
Beta Was this translation helpful? Give feedback.
All reactions
-
Would it also allow overriding the image format with a query parameter? There will be scenarios where I’d want to explicitly specify a format — for example, using PNGs when the image has more lines and using JPGs when the image is more photo-realistic. Of course AVIF does both of these kinds really well, but while we wait for more widespread browser support, the ability to specify the image format would be nice.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 3
-
Provide every possible transformation — The goal of this RFC is to provide the minimal transformations needed
I assume ^this non-goal also covers generating image placeholders? (blurred images, used colours, etc.)
#16832 also doesn't include the use of placeholders so it looks like it isn't a goal for either RFC, but they are one of the best features of next-optimized-images and gastby-image from a UX perspective (I did see the comment about perf issues in #16832, but haven't seen any benchmarks and would like to understand that point more)
Beta Was this translation helpful? Give feedback.
All reactions
-
👀 6
-
Is there any consideration for signing image URLs like Thumbor to prevent URL tampering? Even though you can configure the allowed image domains, this proposal would leave the image endpoint open to denial of service attacks.
From the Thumbor documentation:
Now let’s say that some malicious user wants to overload your service. [They] can easily ask for other sizes in loops or worse, like:
http://some.server.com/unsafe/300x301/smart/path/to/image.jpg http://some.server.com/unsafe/300x302/smart/path/to/image.jpg http://some.server.com/unsafe/300x303/smart/path/to/image.jpgOther than that, the user can ask for images that do not exist, thus forcing us to perform useless http GET operations or filesystem operations.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 8
-
Does this mean that for the first time a request is made an image is generated, and then every subsequent requests will serve the created image? Is it basically a smart image cdn? I guess it will be cleaned between builds though?
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 3
-
At least for the serverless use case, there is not necessarily a permanent filesystem, so resized versions might only be cached on the CDN edge.
Beta Was this translation helpful? Give feedback.
All reactions
-
I'd like to propose a few things to consider adding into this RFC which would be very useful.
- Option to use signed urls for external images instead of white list domains. It would also protect the arguments for hijacking the sizes, quality and so on.
- Possibility to select crop method and positioning (center, top, left, right, bottom, etc)
We wrote a similar solution using vips/sharp (not maintained at the moment) to be able to replace our SaaS for image optimization and manipulation, it explains a bit more what I ment by signed urls and more params to control the image - in case that would be helpful :-)
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 2
-
I would be interested in an x,y argument for cropping.
Beta Was this translation helpful? Give feedback.
All reactions
-
How would this work for generated static sites?
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 8
-
Non-Goals
- ...
- Support for
next export— The goals of the RFC and it's particular characteristics of on-demand optimizing over optimizing at build time which causes build time slowdowns
I think optimizing at build time its valid in a lot of use cases and it does not require to have serverless support to handle the requests, I do agree that it should have some sort way to only transform images once and skip for subsequent builds.
Maybe add a new RFC for this? It is one of the most used features in some frameworks.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 6
-
This would be similar to Gatsby, which smashes resized images into the bundle and relies heavily on build caching. I always found it to be a cool feature on paper, but often unwieldy in practice.
Beta Was this translation helpful? Give feedback.
All reactions
-
@Sever1an can you elaborate a bit why it's not useful in practice? I'm working with Gatsby right now and would love to hear your thoughts 🙌
Beta Was this translation helpful? Give feedback.
All reactions
-
@frederickfogerty It is useful, just has some limits in practice. It has been a while since I last used Gatsby, some of this might be better now. Just brainstorming some frustrations:
-
One of the biggest issues for me was building time, particularly when it got into the realm of tens of minutes. The image resizing step was an extra kind of punishment for running
gatsby cleanin a lot of cases for me. -
While offering support to other developers I found that the interplay between
gatsby-imgand the graphql requests for image sizing was a frequent source of confusion. -
There was no process for expiring sized images in the build cache, so our CI cache just kept getting larger.
-
Offering
fixedandfluidmode in<Img>forces developers to understand browser responsive image technology, which they are often desperately trying to avoid. -
More generally on build time, not totally related to image sizing, but while I am ranting. The paradigm of making a query to build lots page data in
gatsby-nodeat once instead of page queries resulted in many saves in preview mode taking an extremely long time re-building unchanged data for many unrelated pages.
Beta Was this translation helpful? Give feedback.
All reactions
-
Thanks for the info @Sever1an! It's good to know a bit more about the pain points of gatsby-image (and gatsby-transformer-sharp)
Beta Was this translation helpful? Give feedback.
All reactions
-
This is a great RFC, I am doing so already with Sharp, Vercel and NextJS. It works well, and Vercel gives good Cache Control.
- Are there any considerations for the user controlling the http cache headers for the images returned by
_next/image?
Some truly unique remote URLs will probably not change and can be cached after they are resized. Others like /_next/image/?logo.webp may need to be expired.
Deploys cannot be relied upon to clear the cache either as this is online image processing.
- Some S3 best practices are no public access by default and for CORS policies for websites fetching assets from S3 or through Cloudfront CDN.
Since this is server side fetching credentials would be required for the server to access non public assets. This prevents DDoS and therefore requires no next support for masked URLs.
This may mean a user must supply a function that can fetch the image, it is not available over HTTP, or is only available securely over HTTP with environment variables. Would this be supported?
Thanks 👍
Beta Was this translation helpful? Give feedback.
All reactions
-
What would be the HTML output of such component and how would responsive imagery be achieved? Sometimes you want to serve images of with 500 width on medium screens, but only 300 on larger screens because of tiling or something. This is of course achieved through the sizes attribute on the img tag. I very much like the idea of query parameters. You can add a sizes s query that adds media queries.
Beta Was this translation helpful? Give feedback.
All reactions
-
What about DDOS? For example somebody makes thousands request with random query on _next/image?url=/logo.png&w=100&h=100&q=70
Beta Was this translation helpful? Give feedback.
All reactions
-
With a source image that is 2000x2000 px, there are 4M possible requests that can filter through the cache to the origin, combined with say 50 reasonable quality settings you might have 200M. If each image resizing job takes 500ms on Lambda, an attacker could wrack up an AWS bill on the order of thousands of dollars.
It may not be more viable than other DoS attacks, but it is worth consideration.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 6
-
It would be trivial to blow past the fair-use execution limits on Vercel as well without some mitigation.
Beta Was this translation helpful? Give feedback.
All reactions
-
Indeed - that's one of the reasons why I think this sort of feature shouldn't be inside Next.js. It brings more cases at the infra level and not entirely related to the framework. It's like wanting to hit everything nail-like-shape with a hammer.
Unless.... on build time next creates a list of the valid urls that the image service should process, like a sort of whitelist.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 2
-
Unless.... on build time next creates a list of the valid urls that the image service should process, like a sort of whitelist.
Yes, or alternative solution presets (like https://docs.imgproxy.net/#/presets ). I integrated at my company a similar service and this case created for me a problem. I chose presets
quality settings you might have 200M.
Or more - 2000(width) * 2000(height) * 100(quality) * 3(types) = 1 200 000 000
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
It seems unlikely that anyone actually would want this service to distort the images by stretching or adding blank bars. Limiting the specification to a single dimension constraint like max-width or max-side (with the other inferred by native image aspect ratio) would drastically decrease the URL space.
Modal quality settings like { low, medium, high, full } would help a lot too.
2,000(max-width) * 4(quality) * 2 [webp, jpeg] = 16,000 (maybe a few dollars on Lambda)
Beta Was this translation helpful? Give feedback.
All reactions
-
I wonder if image optimization is going to support rewrites? This could be helpful for adaptation and incrementally adopting Next.js.
Beta Was this translation helpful? Give feedback.
All reactions
-
The dream come true in v10.
I just came here to say thank you for being the best react framework ever ❤️
Beta Was this translation helpful? Give feedback.
All reactions
-
❤️ 4
-
Would love to see alternative storage options. Right now I'm assuming images get stored on disk, but with a large enough quantity of images we might eat up all the available storage on whatever server we are using. It also means we will be discarding these image caches if using Blue/Green deployments.
If we could select an S3 bucket, for example, to store images we could mitigate this storage problem
Beta Was this translation helpful? Give feedback.
All reactions
-
Is Fallback optimize image to original format available at the moment?
Beta Was this translation helpful? Give feedback.