The Genius of NextJS and Gatsby as Static Site Generators
Tags: webdev, gatsby, nextjs, react
Published: 2020-07-30 19:32:20

At Agility CMS we've chosen to create starter sites for both NextJS and Gatsby.  Both are static site generators built on top of React, but they take a very different approach to how they actually generate the static html/js/css for a website.
Or do they?

{% github agility/agilitycms-nextjs-starter-2020  no-readme %}

{% github https://github.com/agility/agility-gatsby-starter no-readme %}


They both actually do one thing in a very similar way, and I think it's just genius: they give you a "hook" to specify the JSON data that will be used to generate the output for the site.  This ends up being the "props" variable that gets passed to your React components.  This data is used both during the build process on the server and also ON THE CLIENT SIDE.

That's right - your React code is executed during BUILD time and also in the BROWSER, so the execution of your code can happen in 2 different contexts.  That's a little weird, at first, but if you're smart about it, you can make this work for you.

First of all, having that JSON data available is what makes NextJS and Gatsby pretty magical. It means that, as a framework on top of React, they can route pages after the first page-load without doing a full page reload - all that's needed is that extra JSON and whatever extra dependencies are on the new page.

You can see this on pretty much any Gatsby or NextJS site - if the developers have used the `<Link>` component correctly.

One area where I saw a huge performance improvement was on a listing page.  Check out the blog listing page here:  https://agilitycms.com/resources/posts 

Originally, this page was rendered on the front-end using [this module](https://github.com/agility/Agility-AspNetCore-ReactSampleSite/blob/master/Website/wwwroot/src/components/post-listing.jsx):  which had to do calls back to the server every time more posts needed to be loaded.

```javascript
loadMore(skip, take) {

        var url = `/Listing/Posts?skip=${skip}&take=${take}`

        fetch(url)
            .then(response => response.json())
            .then(data => {

                let noMore = false;
                if (!data.posts || !data.posts.length || data.posts.length == 0) {
                    noMore = true;
                }

                this.setState(prevState => ({
                    posts: prevState.posts.concat(data.posts),
                    loadingMore: false,
                    skip: data.skip,
                    take: data.take,
                    noMoreData: noMore
                }));

                
            }).catch(err => {
                console.warn("An error occurred while loading more data...", err);
                this.setState(prevState => ({
                    loadingMore: false,
                    noMoreData: true
                }));
            });

        return false;
    }
```

##Gatsby
With Gatsby, we were able to get all the data we needed for loading posts at BUILD time with a `<StaticQuery>` and then use an `<InfiniteScroll>` component to render that on the client-side.  

The big win here? No calls back to the server! 

Here's the main component that loads the list of posts:  https://github.com/agility/agility-website-gatsby/blob/master/src/modules/PostListing.js 

```javascript
export default props => (
	<StaticQuery
		query={graphql`
		query PostListingQuery {
			allAgilityBlogPost(filter: {properties: {referenceName: {eq: "blogposts"}}}, sort: {fields: customFields___date, order: DESC}) {
			  nodes {
				contentID
				customFields {
				  date(formatString: "MMMM D, YYYY")
				  excerpt
				  title
				  uRL
				  postImage {
					url
					label
				  }
				}
			
			  }
			}
		  }
        `}
		render={queryData => {

			let posts = queryData.allAgilityBlogPost.nodes;

			const viewModel = {
				item: props.item,
				posts: posts
			}
			return (
				<ReusablePostListing {...viewModel} />
			);
		}}
	/>
)
```

Here's the reusable component that actually renders out the posts with the InfiniteScroll component:  https://github.com/agility/agility-website-gatsby/blob/master/src/components/reusable-post-listing.jsx

```javascript
loadMorePosts(skip, take) {

		let noMore = false;

		let thesePosts = [];
		if (skip >= this.allPosts.length) {
			noMore = true;
		} else {
			thesePosts = this.allPosts.slice(skip, skip + take)
		}

		this.setState(prevState => ({
			posts: prevState.posts.concat(thesePosts),
			loadingMore: false,
			skip: skip,
			noMoreData: noMore
		}));		
	}
```


##NextJS

The same logic holds for NextJS websites built with Agility CMS.  

Check out this Post Listing example from the starter site.  https://github.com/agility/agilitycms-nextjs-starter-2020/blob/master/components/agility-modules/PostsListing.js

While Gatsby has a <StaticQuery> component that renders data from GraphQL, the Agility CMS NextJS project uses a "getCustomInitialProps" method that allows you to do any data fetches at BUILD time, and then NextJS provides that JSON data to the component at render time and on the client for use.

```javascript
PostsListing.getCustomInitialProps = async function ({agility, channelName, languageCode}) {
	const api = agility;
		
	//get our posts
	let rawPosts = await api.getContentList({ referenceName: 'posts', languageCode });
		
	return {
		posts
	}
}
```

Note the use of the <Link> component in both examples.

This is all made possible by 2 amazing static site generation frameworks that are making it easier to make a faster web.

---

## Get Started Now
Get started on a free Agility CMS account today to test out Gatsby or NextJS with starter solutions pre-configured and ready to go.  [Sign up here](https://agilitycmsc.com/free).