Using the Next image component with Kentico Kontent assets
The Next image (next/image
) component has built-in "Automatic Image Optimization" features, which gives you lots of cool stuff like lazy-loading, resizing, and optimisations such as transcoding to modern formats like webp (when supported). The component was added to Next in v10 and worked really well in development and if you were hosting on Vercel, or using one of the supported third-party image providers in your project. If you were using other image providers or hosting platforms such as Netlify however then you would run into problems where the component would not work at all, or was only partially supported or implemented.
In Next v10.0.5 a loader
prop was added to next/image
that allows you to use a custom image provider for image optimisation and transformation, and if you are using Kentico Kontent then you already have this capability available to you as it is built into their Delivery API. The Javascript SDK also provides an ImageUrlBuilder
class to make generating the requests to the API super easy.
To use Kontent's Delivery API as a loader
prop you can create and use a function like this:
import { ImageUrlBuilder, ImageCompressionEnum } from '@kentico/kontent-delivery'
const kontentImageLoader = ({ src, width, quality }) => {
const builder = new ImageUrlBuilder(src)
.withWidth(width)
.withQuality(quality || 75)
.withCompression(ImageCompressionEnum.Lossless)
.withAutomaticFormat()
return builder.getUrl()
}
You may also want to consider only applying the loader
if the src
is to a URL on a Kontent asset domain, and fallback to the default or a different loader
if not. The following is an example component that will only apply the kontentImageLoader
based on such conditions:
import { ImageUrlBuilder, ImageCompressionEnum } from '@kentico/kontent-delivery'
import NextImage from 'next/image'
const kontentAssetHostnames = [
'assets-eu-01.kc-usercontent.com',
'preview-assets-eu-01.kc-usercontent.com'
]
const srcIsKontentAsset = (src) => {
try {
const srcUrl = new URL(src)
return kontentAssetHostnames.includes(srcUrl.hostname)
}
catch {
return false
}
}
const kontentImageLoader = ({ src, width, quality }) => {
const imageUrlBuilder = new ImageUrlBuilder(src)
.withWidth(width)
.withQuality(quality || 75)
.withCompression(ImageCompressionEnum.Lossless)
.withAutomaticFormat()
return imageUrlBuilder.getUrl()
}
const Image = ({ src, width, height, alt, quality }) => {
const loader = srcIsKontentAsset(src)
? kontentImageLoader
: undefined
return <NextImage
src={src}
width={width}
height={height}
alt={alt}
quality={quality}
loader={loader}
/>
}
export default Image
We can now use the above Image
component to get optimisation of images through Kontent's Delivery API, but still take advantage of the rendering smarts of the next/image
component.