August 3, 2021
Adding AMP components to a Next.js webpage

Accelerated Mobile Pages, or AMP, is an open source web components framework that increases the speed of loading webpages. AMP imposes strict guidelines on the HTML, CSS, and JavaScript of a webpage, controlling how external resources like media, ads, and other scripts are loaded.

In this tutorial, we’ll navigate through some of AMP’s guidelines, learning how to manage some of the trade-offs that arise. We’ll cover how to display resource-consuming elements on a webpage while still adhering to AMP’s rules by using AMP components in a Next.js project.

If you wish to follow along, all of the code for this tutorial is available on my GitHub. Let’s get started!

Limitations of AMP

AMP optimizes webpage loading by preventing developers from using custom elements that include resources like images, video, and audio. Similarly, developers can’t write custom JavaScript for tasks like displaying dynamic ads, embedding social media posts, and creating interactive forms. To work around these limitations, we’ll use AMP components.

AMP components

AMP components are custom-written pieces of HTML that we can use to add complex features to our webpage while still remaining compliant with AMP’s standards.

Currently, the AMP component catalog includes built-in components for many common tasks, like adding images, calculating webpage analytics, and displaying ads. Because built-in components are included in the base library of AMP, you don’t need to include them explicitly in your code.

Extended components are extensions to the base of the library and are not included by default. In your code, you’ll need to include extended components explicitly as custom elements. For example, you may wish to add page analytics with amp-analytics or add a lightbox with amp-lightbox.

The catalog also includes experimental components, which are released but not yet supported for wide use. If you can’t find what you need in the component catalog, you may wish to write your own AMP component!

Now that we know what AMP components are available, let’s add one to a webpage!

Turn a webpage into an AMP page

Before we can add an AMP component to our webpage, we’ll need to configure our webpage as an AMP page. The amp configuration accepts two types of values, true and hybrid. Entering a value of true turns the webpage into an AMP HTML page. Entering a value of hybrid creates two versions of the webpage, one in AMP HTML and one in standard HTML, with standard HTML as the default.

Let’s configure our webpage as an AMP page with true:

export const config = { amp: true }

Now, let’s create a true AMP page by running the code block below:

export default function Page = () => {
return <h1>My First AMP Page</h1>
}

When we export the true AMP page, Next.js will create two versions of the page, an optimized version for your users and an unoptimized version for search engines.

To create a hybrid AMP page, all you have to do is change the configuration value of the page to hybrid:

export const config = { amp: ‘hybrid’ }
export default function Page = () => {
return <h1>My First AMP Page</h1>
}

To visit the AMP page, you’ll need to add ?amp=1 to the end of the URL. Additionally, because hybrid isn’t a boolean value like true, you’ll need to surround it with quotes.

Hybrid AMP pages require you to write valid HTML for both AMP and standard HTML pages. To render the correct HTML, we can use the useAmp React Hook.

Importing the useAmp React Hook

Add the useAmp React Hook to your webpage by importing the package below:

import { useAmp } from ‘next/amp’

Next, create a variable that saves the output of the React Hook:

const isAmp = useAmp()

Now, you can use either a ternary operator or an if statement to render the correct HTML:

{isAmp ? (
// AMP component
) : (
// Standard HTML
)
}

Finally, we’ll put everything together! In the example below, we’ll use amp-img, an AMP component that loads images, to display an image on our webpage:

import { useAmp } from “next/amp”;
import Image from “next/image”;

export const config = { amp: “hybrid” };

export default function Hybrid() {
const isAmp = useAmp();

return (
<div>
<h1>Hybrid AMP Page&lt;/h1>
{isAmp ? (
<amp-img
alt=”A view of the sea”
src=”/chiangmai.jpeg”
width=”640″
height=”360″
></amp-img>
) : (
<Image
alt=”A view of the sea”
src=”/chiangmai.jpeg”
width=”640″
height=”360″
/>
)}
</div>
);
}

In the AMP version in the example above, we don’t have to use the default HTML <img> tag. Additionally, because amp-img is included as a built-in component, we didn’t have to import it into our webpage! If a component from the AMP component library is not included in the base library, we’ll receive the following notification that it requires an external script:

<script async custom-element=”amp-carousel” src=”https://cdn.ampproject.org/v0/amp-carousel-0.2.js”></script>

In Next.js, you’ll need to include this script tag in the head of your document, as seen in the code block below:

<Head>
<script
async
custom-element=”amp-carousel”
src=”https://cdn.ampproject.org/v0/amp-carousel-0.2.js”
></script>
</Head>

Validating AMP pages

Before we export our AMP page, let’s make sure it meets AMP’s requirements. There are plenty of methods for adding validation, for example, npm packages, command-line tools, browser extensions, and the developer console! Let’s take a look at the built-in method for AMP validation in Next.js, amphtml-validator.

During building and exporting, amphtml-validator requires that AMP pages meet the AMP specification. Any warnings or errors will be displayed in the terminal.

For example, let’s say that you try to use a regular HTML <img> tag instead of amp-img. It will result in an error on export, as seen in the code below:

Amp Validation

/hybrid?amp=1 error The parent tag of tag ‘img’ is ‘div’, but it can only be ‘i-amphtml-sizer-intrinsic’.
error The parent tag of tag ‘img’ is ‘div’, but it can only be ‘i-amphtml-sizer-intrinsic’.

> Build error occurred
Error: AMP Validation caused the export to fail. https://nextjs.org/docs/messages/amp-export-validation

If you want to use a custom AMP validator, you can add the path to your custom validation rules in the next.config.js file:

module.exports = {
amp: {
validator: ‘./custom_validator.js’,
},
}

Exporting AMP pages in Next.js

If there are no validation errors, running next export will export all of our pages to static HTML pages. Next.js automatically detects if a page supports AMP and exports the page in the correct format.

As mentioned earlier, a hybrid AMP page will be exported as two files. For example, say we have a hybrid page called pages/blog.js. It would be exported as out/blog.html, a standard HTML page with a client-side React runtime, and out/blog.amp.html, an AMP HTML page.

Next.js will automatically insert a link from the AMP page to the standard HTML page, and vice versa, as seen in the following two code snippets, respectively:

<link rel=”amphtml” href=”/blog.amp.html” />

<link rel=”canonical” href=”/blog” />

If pages/blog.js were a true AMP page, it would export a single HTML file called out/blog.html.

Conclusion

Now, you know how to get started with AMP components in Next.js!

In this tutorial, we covered built-in, extendable, and experimental AMP components, true and hybrid AMP pages, and the useAmp React Hook. Then, we learned how to validate and export AMP pages in Next.js.

At the time of writing, AMP only supports CSS-in-JS for styling. However, support for CSS Modules is being developed, and you can find some workarounds on GitHub.

Similarly, there is no official support for TypeScript. Although it is on the roadmap, there is no scheduled release date yet. As a workaround, you can create a file with custom types called amp.d.ts inside your project and add custom types for AMP.

I hope you enjoyed this tutorial! If you find yourself stuck, leave a comment, and I’ll do my best to help you out.

The post Adding AMP components to a Next.js webpage appeared first on LogRocket Blog.

Leave a Reply

Your email address will not be published. Required fields are marked *

Send