-
Notifications
You must be signed in to change notification settings - Fork 1
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
Replace next image optimization with drupal image styles #93
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Thinking about this, we loose webp support. Not sure if that's a concern, but it is something to note |
@@ -9,27 +9,32 @@ module.exports = { | |||
hostname: process.env.NEXT_IMAGE_DOMAIN, | |||
}, | |||
], | |||
deviceSizes: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you tell me why you chose these breakpoints?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly arbitrary. I took the default values and commented out the ones I didn't want. I tried to get something close-ish to the breakpoints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not align them with the breakpoints of the design system?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh, it's not really necessary IMO. Images don't need to break down at the same breakpoint. Just as long as the image is larger than the area it's in. Almost all images use a css cover property anyways
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a thing to ask what others on the team are doing and how they set up their responsive images. It is in the 'doesn't really matter' category but this seems like a good opportunity to engage and align with others.
lib/libguides.tsx
Outdated
@@ -21,6 +21,7 @@ const fetchLibGuides = async ({accountId, subjectId}: { accountId?: number, subj | |||
} | |||
|
|||
const guidesConfig = { | |||
next: {revalidate: 1}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tells next to only cache the fetch
call for 1 second.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aye, but why is it in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷 it was in my local code, so i just committed it with the stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, if you want it in then I guess it stays in.
It would be great if you could write out an RFC-style document that details how the ISR invalidation is intended to work so that I could have something to compare this to. That would also be helpful documentation for the SUP project.
{w: 1200, s: 'breakpoint_xl_2x'}, | ||
{w: 3840, s: 'breakpoint_2xl_2x'}, | ||
]; | ||
const style = imageStyles.find(s => s.w === width)?.s || 'breakpoint_xl_2x'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Writing this out in English so my brain is happy.
For all images, that are not local or relative, try and match an image style to an image width, if no matching image width to the array of imageStyles, default to the biggest image style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example: https://github.com/SU-SWS/sulgryphon-nextjs/blob/1.x/components/paragraph/stanford-card.tsx#L43
That wouldn't get all the src set values (128, 384, 750, 1200, 3840) because it doesn't set the sizes
key? It would just render as the one size?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
opposite of what you ask. If you don't specifiy the sizes
property, it will use the default from next.config.js.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha thanks.
So the convention and recommendation would be to supply a sizes property wherever images are being used, otherwise the largest image will be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no no... It's recommended to use the default values. Maybe unless you are displaying a small image and don't need the large versions. If you don't pass a sizes
property when using an <Image>
it will make a responsive image using the sizes defined in the next.config.js which should be the most ideal in most situations I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, ok, this info is something that @jenbreese will find helpful/useful when she gets going on the SUP project.
next.config.js
Outdated
imageSizes: [ | ||
// 16, | ||
// 32, | ||
// 48, | ||
// 64, | ||
// 96, | ||
128, | ||
// 256, | ||
384 | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What unit are these in? I'm not fully grokking the documentation
https://nextjs.org/docs/app/api-reference/components/image#imagesizes
https://nextjs.org/docs/app/api-reference/components/image#sizes
Do you have an example I can follow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://html.com/attributes/img-srcset/#Specifying_Image_Width
So it tells the browser the size of the image... which isn't really accurate, but it's something
<img alt="" loading="lazy" decoding="async" data-nimg="fill" class="su-object-cover su-object-center" style="position: absolute; height: 100%; width: 100%; inset: 0px; color: transparent;" sizes="100vw" srcset="https://example.com/breakpoint_lg_2x/image.jpg 750w, https://example.com/breakpoint_xl_2x/image.jpg 1200w, https://example.com/breakpoint_2xl_2x/image.jpg 3840w" src="https://example.com/breakpoint_2xl_2x/image.jpg">
Do you have to do anything to support pixel density (1x and 2x)? |
Oh and one last thought, what about cache control? https://nextjs.org/docs/app/api-reference/components/image#caching-behavior |
Nothing provided to handle that
The image src urls are changed to target the Drupal site directly. So the cacheing would be on the Acquia side. A problem I found recently though is this implementation requires the |
const style = imageStyles.find(s => s.w === width)?.s || 'breakpoint_xl_2x'; | ||
// Switch the image style for the desired width. Add the width parameter just to prevent console logs. | ||
// https://nextjs.org/docs/messages/next-image-missing-loader-width | ||
return src.toString().replace(/styles\/\w+\//, `styles/${style}/`) + `&w=${width}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However unlikely, in theory, the src string could already have a w
parameter. It would be safer to put the URL through new URL
and then set the searchParams instead of concatenating the string.
eg: https://nextjs.org/docs/app/api-reference/next-config-js/images#fastly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that too. It would be more bullet proof that way, but since we're only ever pulling images from Drupal, there shouldn't ever be that param.
FYI, I'm still not 100% convinced myself of this approach since it requires insecure derivatives in the Drupal side. What are your thoughts on that |
By skipping the Next/Vercel optimizations and going straight to Drupal without secure derivatives we are removing the DoS flood protection on Drupal and limiting the styles/sizes that can be produced to the image styles available in the Drupal install. Overall, I don't think we've had many issues with DoS attacks on our image derivatives and we have better logging/reporting/blocking on Acquia than we do currently on Vercel so this seems like a valid trade. However, if we are going to remove the secure token, why not just re-write the image paths, like you had before, to remove any and all URL parameters and force the image source to always be the original file? Wouldn't that get around the URL parameter 'source' issue on Vercel and allow this site to continue to use Next's image optimizations and Vercel's Edge network caching? |
From what it seems, it doesn't matter if we rewrite the urls. Vercel still treats each request as a unique value. I tried to implement a middleware for the |
Remote image invalidation is supported by a cache query param: https://vercel.com/docs/image-optimization#remote-images
But I am surprised you cannot re-write the URL to drop the extra params before the route is hit or provide the middleware to validate that the request came from a legit page render by using a CSRF token or something. I submitted a support request with Vercel One thing we may want to do is forego fetching from the image styles directory at all and always pull the original source image from sites/default/files. Optimize on Vercel for different sizes of the one source file instead of optimizing on the already optimized file on the image derivative. |
Reply from Vercel support
Filtering Query Parameters |
I kinda had a thought about the whole itok thing... what if we removed the use of the image styles like you mentioned. then in the components, it will be fetching the original image which doesn't need an itok at all. This would eliminate the sql injection getting appended to the parameter. However, I don't think it solves the whole problem, because based on the documentation, a bot can just add it to the |
That sounds like an improvement to me. As far as parameters go, I think your rewrite is helping and can continue to help. If you can adjust it to allow only the -- Removed Monitoring Discussion and Links To Focus On This PR -- |
1da44a6
to
c8b984d
Compare
Closing this since we seem to be doing good since the issue. |
READY FOR REVIEW
Summary
Steps to Test