Implements all code necessary to lazy-load images for a NextJS site, SPECIFICALLY for images that are initially only available as Portable Text blocks.
Why is Portable Text a complication?
Portable text is really convenient for most things. However, for image blocks, getting lazy loading the "right" way is hard to nail down for a number of reasons:
You don't have access to all of the image data - just reference information used internally by Sanity
You need an image URL to use with the Image component, which is not immediately-available in this data
Either use @sanity/image-url to generate the URL with many different configuration options OR...
Manually-query the full image data using the _ref value
This is the route I opted for since the image data also includes a metadata.lqip field, which is a pre-made base64 encoded 20x20 image that's useful for placeholders (e.g., the blur image used as part of lazy loading)
There is no apparent way to load the embedded images via the base query used in getStaticProps
The closest you can get is by querying the field that actually contains the Portable Text blocks - in my case, the body field
The metadata.lqip field isn't mentioned much in the docs, but it does seem to exist for the purpose of placeholder images
The docs seem to imply you should use the @sanity/image-url package, but doing so requires you to make some faulty assumptions about the images being generated (namely, there is an implicit assumption that they are all the same size, which leads to funky resolutions in many images)
To me, it seems better to use the base image asset, then use something like sharp to resize the image correctly (instead of with flat height/width values); while the resize logic is happening, lazy load should take effect, but this is not currently fully configured yet
CORS Considerations
ArticleBodyImage actively-queries the CDN for the images on-the-fly (from the browser), meaning, for that component, the request is not originating from the same origin (as requests from getStaticProps are). As a result, the request from this component will be blocked unless you've added the domain your application is running at as an allowed origin.
If you encounter issues with CORS when fetching data from Sanity CMS, make sure you've added the correct allowed origin in your Sanity project Dashboard (under the "API" tab).
Implements all code necessary to lazy-load images for a NextJS site, SPECIFICALLY for images that are initially only available as Portable Text blocks.
Why is Portable Text a complication?
Portable text is really convenient for most things. However, for image blocks, getting lazy loading the "right" way is hard to nail down for a number of reasons:
Image
component, which is not immediately-available in this data@sanity/image-url
to generate the URL with many different configuration options OR..._ref
valuemetadata.lqip
field, which is a pre-made base64 encoded 20x20 image that's useful for placeholders (e.g., the blur image used as part of lazy loading)getStaticProps
body
fieldmetadata.lqip
field isn't mentioned much in the docs, but it does seem to exist for the purpose of placeholder images@sanity/image-url
package, but doing so requires you to make some faulty assumptions about the images being generated (namely, there is an implicit assumption that they are all the same size, which leads to funky resolutions in many images)sharp
to resize the image correctly (instead of with flat height/width values); while the resize logic is happening, lazy load should take effect, but this is not currently fully configured yetCORS Considerations
ArticleBodyImage
actively-queries the CDN for the images on-the-fly (from the browser), meaning, for that component, the request is not originating from the same origin (as requests fromgetStaticProps
are). As a result, the request from this component will be blocked unless you've added the domain your application is running at as an allowed origin.If you encounter issues with CORS when fetching data from Sanity CMS, make sure you've added the correct allowed origin in your Sanity project Dashboard (under the "API" tab).