-
Notifications
You must be signed in to change notification settings - Fork 3
Image and video optimizations #1769
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
Conversation
… be wrapped error)
| <DesktopOnly> | ||
| <PlatformLogoInverted | ||
| unitCode={name as OfferedByEnum} | ||
| height={50} | ||
| /> | ||
| </DesktopOnly> | ||
| <MobileOnly> | ||
| <PlatformLogoInverted | ||
| unitCode={name as OfferedByEnum} | ||
| height={40} | ||
| /> | ||
| </MobileOnly> |
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.
Here we produce for each side of the width breakpoint and use the css media query to hide one. This is wordy, though needed for varying the height with only CSS.
Where the images are in the repo we can generally pull them in as static imports, so don't need to specify the dimensions, though in this case the ol-components PlatformLogo is not allowed to import from outside its workspace.
Further, the width and height on <Image> components do not size the image itself - it is just to block space to prevent layout shift, which can be done with CSS. Here though the logos are of different sizes so we need to hardcode the dimensions (here providing fixed height with width calculated in PlatformLogo).
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.
Where the images are in the repo we can generally pull them in as static imports,
That's why Logo.tsx specifies the dimensions, but we shouldn't have to here, right? I think you can achieve the same effect just with
const PlatformLogoInverted = styled(PlatformLogo)(({ theme }) => ({
filter: "saturate(0%) invert(100%)",
height: 50,
maxWidth: "100%",
[theme.breakpoints.down("md")]: {
height: 40,
width: "auto",
},
}))
Probably a separate Issue: Doesn't seem great to be specifying aspect ratios / widths in Logo.tsx. Maybe we should just move the enum'd labels to ol-components. I guess we probably need to static string paths for email templates or something. (Taking a quick look.... maybe we don't use them anyway in the backend.)
| current="Departments" | ||
| /> | ||
| } | ||
| backgroundUrl={backgroundSteps.src} |
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.
The <Banner> component has a default image path (background_steps.jpg), but as this is just a path string, the image is loaded directly as opposed to from the image optimization endpoint. Static imports get the image optimzation endpoint, but as a rule the <Banner> component cannot import from outside ol-components.
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.
Assuming we publish ol-components as a separate package, and I guess this could wait until then, we should do one of the following:
- Not include Banner in ol-components, move it to
main/src/components - Remove the string-based default background image from Banner Doesn't make sense unless I guess it's an absolute / fully qualified URL to some server somewhere.
- Move the default background image to ol-components.
I would probably lean toward (1). Our Banner component has lots of props enabling it to be used for (A) simple cases like /departments, /topics, etc, and (B) complex cases like the unit channel pages. I'd be happy to include (A) in the published design system, but (B) seems too Learn-specific. I think the two cases are different components in Figma, too.
ChristopherChudzicki
left a comment
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 is working great. I left a few comments, some of which we should probably make sense to do now (remove comments, maybe use backgroundSrcSetCSS more, add fallbak to backgroundSrcSetCSS?).
| <SubHeaderImageContainer> | ||
| <SubHeaderImage | ||
| src={domeImage} | ||
| alt="A view of the entablature of MIT's Great Dome" |
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.
today i learn...
| <DesktopOnly> | ||
| <PlatformLogoInverted | ||
| unitCode={name as OfferedByEnum} | ||
| height={50} | ||
| /> | ||
| </DesktopOnly> | ||
| <MobileOnly> | ||
| <PlatformLogoInverted | ||
| unitCode={name as OfferedByEnum} | ||
| height={40} | ||
| /> | ||
| </MobileOnly> |
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.
Where the images are in the repo we can generally pull them in as static imports,
That's why Logo.tsx specifies the dimensions, but we shouldn't have to here, right? I think you can achieve the same effect just with
const PlatformLogoInverted = styled(PlatformLogo)(({ theme }) => ({
filter: "saturate(0%) invert(100%)",
height: 50,
maxWidth: "100%",
[theme.breakpoints.down("md")]: {
height: 40,
width: "auto",
},
}))
Probably a separate Issue: Doesn't seem great to be specifying aspect ratios / widths in Logo.tsx. Maybe we should just move the enum'd labels to ol-components. I guess we probably need to static string paths for email templates or something. (Taking a quick look.... maybe we don't use them anyway in the backend.)
| current="Departments" | ||
| /> | ||
| } | ||
| backgroundUrl={backgroundSteps.src} |
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.
Assuming we publish ol-components as a separate package, and I guess this could wait until then, we should do one of the following:
- Not include Banner in ol-components, move it to
main/src/components - Remove the string-based default background image from Banner Doesn't make sense unless I guess it's an absolute / fully qualified URL to some server somewhere.
- Move the default background image to ol-components.
I would probably lean toward (1). Our Banner component has lots of props enabling it to be used for (A) simple cases like /departments, /topics, etc, and (B) complex cases like the unit channel pages. I'd be happy to include (A) in the published design system, but (B) seems too Learn-specific. I think the two cases are different components in Figma, too.
| } | ||
| title="Browse by Topic" | ||
| header="Select a topic below to explore relevant learning resources across all Academic and Professional units." | ||
| backgroundUrl={backgroundSteps.src} |
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.
Any reason not to use backgroundSrcSetCSS here?
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.
For this one the getImageProps() only produces the single 1x image, so using srcset has no impact.
Also, the backgroundUrl prop is used in the <Banner> css like linear-gradient(rgba(0 0 0 / ${backgroundDim}%), rgba(0 0 0 / ${backgroundDim}%)), url('${backgroundUrl}'), so we needed some extra gymnastics:
const backgroundUrlFn = backgroundUrl.startsWith("image-set(")
? backgroundUrl
: `url('${backgroundUrl}')`
Works fine though.
frontends/ol-utilities/package.json
Outdated
| "iso-639-1": "^3.1.0", | ||
| "lodash": "^4.17.21", | ||
| "moment": "^2.29.4", | ||
| "next": "^14.2.15", |
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.
Doesn't really matter, but I'd make this a peer-dep along with react.
| }) | ||
| .join(", ") | ||
|
|
||
| return imageSet ? `image-set(${imageSet})` : "" |
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 don't understand when props.srcSet, and hence imageSet would be undefined. But I guess it can be?
Should this fall back to url(`${props.src}`)?
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.
props.srcSet is typed string | undefined, though I'm not sure how it could be. Either way the backround image would be broken, so have removed the ternary.
|
|
||
| const DEFAULT_WIDTH = 200 | ||
|
|
||
| export const PlatformLogo: React.FC<{ |
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.
Should we have separate PlatformLogo and UnitLogo components?
ChristopherChudzicki
left a comment
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.
👍
ChristopherChudzicki
left a comment
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 are the relevant tickets?
Closes https://github.com/mitodl/hq/issues/5857
Upgrades to Next.js v15
Description (What does it do?)
Replaces
<img>tags with<Image>components where it makes sense to.There are places where it doesn't make sense to, such as where we have containers that would prevent layout shift and where we are already able to provide the image as a static import (Next.js set the
srcstring to its image optimization endpoint), e.g. the PersonalizeSection image.Static imports for images in repo (import src is a path to the Next.js image optimization endpoint). This is used for both
<img>tags and CSS background-image.Provides a utility that produces a CSS
image-set()declaration for a statically imported image. These are links for the image from the optimization endpoint at resolutions for 1x and 2x screen pixel densities, see https://developer.mozilla.org/en-US/docs/Web/CSS/image/image-set. Applied to the homepage personalize section background. These can also be used on<img>tags (srcset attribute). We should consider applying elsewhere, particularly for large images, though also should use with caution as it may not be desirable to render high resolution images for example for backgrounds that contain little detail.The resource drawer images are now optimized by Next.js with noticeable improvement to quality:
Before:

After:

Resource drawer YouTube videos are displayed using a simple iframe (YouTube's embed html is similar). Non-YouTube videos fall back to Embedly, though all of our videos are YouTube at present. This also removes some padding added by Embedly and sizes the videos to match our aspect ratios and applies the border radius.
Before:

After:

Updates ol-components/Logo to support unit logos and distinguish between units and platforms so it can be used on the unit channel pages. We can't import from the
./public/imagesfolder to use image optimization as we have the rule that ol-components are leaf imports, though there is no value for SVGs.Clean up repetitions of the Embedly key / move into EmbedlyCard.
How can this be tested?
Check that images and logos display correctly at mobile and desktop. Particular attention to: