SEO and Image Optimization with Next.js
Tags: javascript, react, tutorial, nextjs
Published: 2020-08-02 16:46:08

*This blog is part of a series where I document rebuilding a website that relies on HTML, CSS and Bootstrap in React.js using the Next.js framework to improve performance, reduce costs and increase my workflow for future changes.*

The finished website: https://wallisconsultancy.co.uk
The source code: https://github.com/james-wallis/wallisconsultancy

**Want to track users of your website in real time?** [Check out my post about Google Analytics and how to use it with Next.js](https://dev.to/jameswallis/adding-google-analytics-to-any-next-js-app-46h1).

## Intro

For a website to rank highly on Google and have the best chance of generating business, it needs to perform well and be SEO friendly. Fortunately, Next.js has two plugins that can help take our website to the next level.

Now that the Wallis Consultancy website has been re-built it’s now time to focus on the finer details which are:
* SEO specifics (Page titles, descriptions, Open Graph)
* Image Optimisation (Ensure images are as small as possible, load smaller images on mobile, decrease load times)

We can achieve this easily with Next.js and two third party modules.
These are:
* [next-seo](https://github.com/garmeeh/next-seo)
* [next-optimized-images](https://github.com/cyrilwanner/next-optimized-images)

*With the release of Next.js 10 a built-in image optimisation component has released. [Checkout my article where I briefly compare it with next-optimized-images](https://dev.to/jameswallis/next-image-and-next-optimized-images-a-brief-comparison-4c4i).*

## next-seo
Next-seo provides the ability to configure SEO focused fields, such as title, description and canonical URL that are found in the `<head>` of a HTML document.

It works by adding a `<NextSEO>` component into a page and passing it props. An example of this for title and description:
```javascript
import React from ‘react’;
import { NextSeo } from ‘next-seo’;

export default () => (
  <>
    <NextSeo
      title=“Simple Usage Example”
      description=“A short description goes here.”
    />
    <p>Simple Usage</p>
  </>
);
```

For some attributes, they don’t change on a page by page basis so next-seo provides the `DefaultSeo` component that can be added to a Next.js `_app.js`. An example of this is using the `twitter` and `openGraph` props:

```javascript
import App, { Container } from ‘next/app’;
import React from ‘react’;
import { DefaultSeo } from ‘next-seo’;

export default class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
    return (
      <>
        <DefaultSeo
          openGraph={{
            type: ‘website’,
            locale: ‘en_IE’,
            url: ‘https://www.url.ie/‘,
            site_name: ‘SiteName’,
          }}
          twitter={{
            handle: ‘@handle’,
            site: ‘@site’,
            cardType: ‘summary_large_image’,
          }}
        />
        <Component {…pageProps} />
      </>
    );
  }
}
```

For wallisconsultancy.co.uk the default next-seo is:
```javascript
<DefaultSeo
	titleTemplate={‘%s | Wallis Consultancy’}
  openGraph={{
  		type: ‘website’,
      locale: ‘en_IE’,
      url: ‘https://wallisconsultancy.co.uk/‘,
      site_name: ‘Wallis Consultancy’,
   }}
/>
```

## next-optimized-images
This package optimises all images in a Next.js application by using `require('filepathToImage')` as the value of the `src` attribute in an `img` tag. It is able to handle jpeg, png, svg, webp and gif file types and can also enable progressive loading and inline small images in addition to reducing their size between 20% to 60%.

As described in the documentation, you need to install additional packages to `next-optimized-images` to take advantage of its optimisation power. As wallisconsultancy.co.uk contains JPG images I also installed `imagemin-mozjpeg`, webp-loader, `responsive-loader` and `sharp`. The latter two packages enable the ability to resize images into multiple sizes at build time - meaning mobiles can be sent smaller images than desktops resulting in faster load times on slower, mobile networks. The `webp-loader` package is a tool that will generate a `webp` type copy of the initial `jpg` image to be shown on devices that support it. `webp` is a next generation file type that has superior file compression to `jpg` making them smaller in size and faster to load onto the page

An example use for the image on the wallisconsultancy.co.uk homepage is:
```javascript
import Layout from ‘../components/layout’

export default function IndexPage() {
  return (
    <Layout pageTitle=“Home”>
      <div className=“flex flex-col md:flex-row”>
        <div className=“w-100 md:w-2/3”>
			...content
        </div>
        <div className=“w-100 md:w-1/3 flex items-center justify-center”>
          <picture>
            <source srcSet={require('../images/mike-wallis2.jpg?webp')} type="image/webp" />
            <source srcSet={require('../images/mike-wallis2.jpg')} type="image/jpeg" />
            <img
              src={require('../images/mike-wallis2.jpg')}
              alt="Mike Wallis"
            />
          </picture>
        </div>
      </div>
    </Layout>
  )
}
```

This will create 2 compressed copies of the image, `jpg` and `webp`. The device will attempt to select `webp` but fallback to `jpg` if it isn't supported. On a device where the `picture` tag is not supported, the `img` tag will be used.

## Google Lighthouse
> Lighthouse is an open-source, automated tool for improving the quality of web pages. You can run it against any web page, public or requiring authentication. It has audits for performance, accessibility, progressive web apps, SEO and more.

*[Google Developers](https://developers.google.com/web/tools/lighthouse)*

Before adding the packages used in this blog, the performance score for Wallis Consultancy was around 70 (mainly as the images sizes were not optimised and not using next generation formats such as `webp`) and the SEO was 60.

After adding the SEO fields and optimising all the images on the website it achieved an almost perfect Google Lighthouse score:
![The Google Lighthouse score for wallisconsultancy.co.uk](https://dev-to-uploads.s3.amazonaws.com/i/djr5nh6me37h1m7zaepc.jpg)

## Roundup

This blog demonstrated the power of two third party Next.js packages `next-seo` and `next-optimised-images`. The former will ensure all the pages are setup to rank highly on search engines and the latter makes each page load that little bit faster. 

In the next blog, the final of the series, I’ll create a Travis pipeline which will deploy the website to Github pages.

### Bonus:
Improving website SEO and performance is a great way to gain more users. Once this is done it’s a good idea to track them and see how real people use your website.  Let me take you through adding Google Analytics to your Next.js app to be able to see this information and more.

**[Adding Google Analytics to Next.js with FAQs.](https://dev.to/jameswallis/adding-google-analytics-to-any-next-js-app-46h1)**