Using AMP Images in NextJS
4 min read
AMP - Accelerated Mobile Page
First things first, what is AMP? It stands for Accelerated Mobile Page and is a web component framework that allows us to easily create user-first experiences for the web. It’s an open-source project by Google and Twitter, and was designed to create really fast mobile pages. If you want to read more about it, check out the official website.
How NextJS integrates AMP
NextJS makes it easy to integrate AMP components in your app, with an advanced feature that’s easily configurable. You can set the configuration on a page by page basis, deciding whether you want each particular page to be an AMP-only page (if the page has no NextJS or React client-side runtime) or a hybrid page (where the page will be rendered as traditional HTML by default, but where you can render AMP HTML by adding ?amp=1
to the URL).
If you’re coding up a hybrid page, NextJS provides a nice useAmp
hook to allow us to differentiate between the two modes. This allows us to create conditional JSX for instance, whereby if useAmp
returns true
, we render an AMP component, and a normal HTML element if otherwise. Read more about how to set this up in NextJS here.
amp-img component
The AMP component I want to focus on today is the amp-img component. Images can really add to the feel and messaging of a web page...but at the cost of potentially slowing load times. The other potentially annoying thing is cumulative layout shift as images are loaded and rendered, which Google heavily penalises. AMP images can really help on both of these counts, as it smartly manages image resources during runtime, and additionally, places images in their rightful place to limit layout shift, due to the fact that we need to pass in an image’s explicit size.
If you want to make a hybrid AMP image component in NextJS, it could look something like this.
import React from 'react'
import Image from 'next/image'
import { useAmp } from 'next/amp'
export const ImageWithAmp = ({ src, alt, width, height }) => {
const isAmp = useAmp()
return isAmp ? (
<amp-img src={src} alt={alt} width={width} height={height} layout="responsive" />
) : (
<Image src={src} alt={alt} width={width} height={height} />
)
}
For the amp-img
component, layout="responsive"
means that the image will be resized based on the aspect ratio set by the weight and height, in response to the size of the viewport. The height and width figures set here don’t actually determine the size of the image that’s rendered - it’s solely used to determine the aspect ratio when layout="responsive"
.
Note that amp-img
is a block element (vs. a standard HTML img
element which is inline), so if you want to set a maximum height (or width) for your image, you’ll need to wrap your amp-img
in a container, and set the max-height on that container. Alternatively, you can set display: inline-block
directly on your amp-image
instead. There are lots of other options, so be sure to read the official docs to see how you might best use this component for your needs.
For the NextJS Image
component, the default layout is intrinsic
if no value is provided. This setting scales the dimensions of the image down for smaller viewports (where the viewport is smaller than one of the dimensions of your image), but maintains the original dimensions for larger viewports. The official docs has some really nice examples for the different options you have, so be sure to check them out.
Thinking of utilising AMP components? Tell me about what components you’re using it on!