-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
feat(gatsby-image): Art Direction SSR fix (compliments hydration fix PR) #26117
feat(gatsby-image): Art Direction SSR fix (compliments hydration fix PR) #26117
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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.
Some of the changes from this commit, were added from this PR to the main hydration fix PR (relevant commit).
These changes would be relevant for rebasing, but have not been added due to the reliance on isHydrated
) which this PR does not presently have any interaction with.
Hey @polarathene, Thanks for doing all this work! It's working and the changes are dope but I don't think it's a good idea to accept these changes. Gatsby-image is already super complex and this makes it even more complex, we should let the user create these classes themselves. They can integrate it better in their CSS story (emotion, styled-components, css-modules, ...). Maybe we should just warn people about it in develop. We never thought art-direction through and now we're here. Sorry for the time you've spent on it. I don't want to close it just yet, so open for feedback. |
`uniqueKey` is a CSS classname friendly base36 string of a 32-bit hash generated from all the image variants `srcSet` values. DJB2a itself is the XOR(`^`) improved version of DJB2, a simple and well known hash function. It has been selected for lightweight footprint and decent performance(minimal overhead), but may suffer slightly compared to FNV1a-32 collision wise. It should be a fairly safe choice to go with, `styled-components` also uses this hash function for a similar purpose. Special care is required for hash functions to work correctly in JS due to it's number type not being a 32-bit native type. Bitwise operators in JS operate in 32-bits however, and `>>>` ensures a positive uint number is returned to match expected hash outputs. Used in future commits for CSS to target, as a short and unique identifier. Only present during SSR, removed once hydrated.
Using the `uniqueKey` CSS class, and `<style>` elements, we can ensure the correct CSS applies for Art Directed images prior to React being ready.
Use the new hash method for `key` prop as well. Original commit for this was lost due to rebase with the other half of the commit was transferred to the hydration fix PR this PR compliments.
Reviewer does not want to merge the feature into `gatsby-image`. Extracted to separate a file as a Higher-Order Component. Reverts changes to `index.js`. Loses key prop improvement with `activeVariant`. May not integrate as smoothly as-is due to changes in hydration fix rendering, may need to keep `uniqueKey` until hydrated. To use, fluid or fixed prop is **expected** to be provided. Import the HOC version `gatsby-image/art-direction` and use as you would `gatsby-image`.
Alternative single `<style>` element with string generated if this commit approach with individual `<style>` element per MQ is a problem: ```jsx return ( <style> {base ? `${base}\n` : ``} {imageVariants .filter(v => v.media) .map(v => `@media ${v.media} { ${variantRule(v)} }`) .join(`\n`)} </style> ) ```
e64a026
to
e179b56
Compare
Rebased onto master, extracted the feature out to a separate file as a HOC and removed any changes that could only be used within the You can reject this PR if you like. I updated the PR with an example HOC for the benefit of anyone that wants the feature but is unsure how to implement it. I have not taken time to test these changes. As it's not a class based component with constructor and has not been modified to use hooks, the renders will perform unnecessary overhead re-calculating values that have not changed. Users on mobile or with fast connections may not experience the issue this PR solves. Might be helpful to link to this PR from the Fixed with latest commitTo anyone that uses the HOC, note that gatsby/packages/gatsby-image/src/index.js Lines 504 to 505 in eaac84b
gatsby/packages/gatsby-image/src/index.js Line 516 in eaac84b
For gatsby/packages/gatsby-image/src/index.js Lines 630 to 632 in eaac84b
You'll need to target it as well as the root tag, so something like As commit message mentions, Also, it's currently being discussed to use |
Added support for optional `maxWidth` and `maxHeight` for `fluid` type images. The internal elements (padding for fluid, bgcolor for fixed) are both lacking class names to target specifically but both are the 1st children. Due to review constraints they are being targeted with a pseudo-selector, if the internal structure changes this will of course break. Note that the `fixed` type image has width/height attributes as well that are hard-coded to the first image in SSR build. Not tested if that causes any problems, I think it might affect `object-fit: cover`, but only with `critical` images where these attr values are used until image request responds(or re-validates if cached).
ee3bd85
to
0c0ae42
Compare
This needs to go into the gatsby-image documentation. Excellent work! |
@polarathene I can open a PR for the dox to include this as a solution until the next delivery includes this out of the box. |
@MaxwellKendall thanks that would be appreciated! 👍 |
Closing, this is fixed in our new gatsby-plugin-image component. Thank you for your contribution! <3 |
Description
Complimentary PR to
gatsby-image
hydration fix, this larger PR fixes the issue prior to React being available while loading HTML.If additional details about lines are needed, check individual commits for extra details or logical grouping.
Notes
Potential changes up for discussion
As media queries cannot be inline styles,
<style>
elements are used within<body>
(unless there is an API to add to<head>
?), or rather eachgatsby-image
component instance. These are removed once React hydrates, so only valid in SSR output. Could change that if there's value in keeping around in the client?The hash could also be used for cache keys instead of
img.src
if any value in that.Hash function implementation
The hash method DJB2a which is the same as what
styled-components
uses should be fine, there isn't any expectation for the results to be compatible with other DJB2a implementations, which might happen if the filepath strings contain chars that exceed a single byte(some languages, emoji, etc), that can be supported if desired but requires more code and adds perf overhead.Further related details in my original PR comments:
image
#24811 (comment)image
#24811 (comment)<noscript>
support not addedOld comments
This has not presently catered for
<noscript>
, which if desired, I'll revert to a previousResponsiveQueries
components in my original PR that used string concatenation with all CSS in a single<style>
instead of one<style>
per media condition + fallback/base.There is presently a PR actively discussing if
<noscript>
logic can be changed to drop the string variants supporting it without bumping the min React to 16.5+, or we can alternatively hold off until a v3 with breaking changes.Let me know if catering to
<noscript>
is presently worth the time(it's already partly out of sync IIRC).EDIT: Shouldn't actually be a problem since this is only relevant for the SSR payload, and targets the root tag of the component.
Not exactly HTML spec compliant, but other popular packages use same approach
While browsers support this approach(and that libraries like Emotion apparently use this technique),
<style>
elements within body is technically against spec, and thus may be flagged if anyone has some CI / validation checks on HTML spec conformance.There's not much we can do about this without some SSR API improvements, or adopting some CSS-in-JS library.
Prior comment in original PR about
<style>
approach considerations: #24811 (comment)Related Issues
Related: #24748 (comment)
Related: #24811 (Original PR)