I recently have been looking into some frameworks that would make my life easier as a ReactJS developer. I perused several articles and blog posts on the numerous big ReactJS frameworks out there. I had come across Gatsby and NextJS, I knew of Create React App (which isn't a framework technically but I'll mention it all the same), then there were specific frameworks for very specific apps, like Hydrogen. There were some key features I wanted to have the flexibility of leveraging when needed.
In this article I will discuss the following:
- Why I decided to utilize NextJS for my app idea
- Why I will continue using NextJS
- Demonstrate how NextJS can be used to implement the wide variety of approaches we as web developers can take when starting a project or product
Why NextJS?
First, I developed a list of the variety of handling I preferred my framework to offer:
- Routing
- SSR (Server-side rendering)
- SSG (Static Website Generator)
- SPA (Single-Page Application)
- SEO Optimization
- State Management
Some more details I wanted to take into consideration:
- Community Support
- Time to market
I knew I needed to lean on a framework or engine for generating projects because I didn't want to spin up an entire infrastructure from scratch every time I started a new project.
Ideally, my priorities were to have the capability of evaluating a project, its feature set and requirements knowing full well the framework I become well versed in has my back when I make critical development decisions. I didn't want something that was overkill with too much boilerplate. My priority was to avoid package bloat where I could while still maintaining the list of offerings I wanted to prioritize, so Create-React-App frankly was removed from my go-to list as a result.
Now let's talk about Gatsby briefly. It is an SSG, it doesn't support the variety of web design patterns I hoped for, so ultimately long story short, that is why I didn't pursue utilizing Gatbsy. Though it was a strong contender and I will give it a try soon.
There were other frameworks I came across like Hydrogen that were hyper-specific. Hydrogen is a framework for developing Shopify custom storefronts, so that didn't work.
Why I will use NextJS in the future
We finally arrive at examining NextJS. NextJS supports nearly every option on my list. NextJS elegantly can handle SPA, SSG, SSR, Routing, SEO Optimization. NextJS has excellent community support and quick time to market through utilization of Vercel for deployments. Although NextJS doesn't incorporate state management straight out of the box that can be integrated with no major complication.
How NextJS supports different approaches
First off, let's discuss Routing.
I've always liked the natural organization that came with projects that handle server-side rendering. Most well-structured SSR-based apps will have the primary pages live at a specific folder path. This is the case with NextJS and its in-house routing handling. Adding new pages and routes is made incredibly easy through the usage of the folder hierarchy. If you want a new page at a specific route, simply add a folder or file /pages
within your NextJS app. NextJS will generate the route for you based on your naming convention of the added file or folder!
Let's take a look at an example of the ease of adding routes with NextJS:
As you can see here, I added a series of folders and files under pages. pages/_app.js
is bootstrapped in by NextJS, as is the pages/index.js
. The index.js file is the root of your app, typically your home page. You can see the folders I've added pages/categories/[category].js
and pages/posts/[slug].js
as well.
How about we break these two file types down?
Let's say that I have a blog web app. A blog is meant to feature a series of posts and can be divided into categories. Therefore you might want a routing setup like the following https://myfoodblog.com/categories/dessert and https://myfoodblog.com/posts/how-to-make-chocolate-cake. You can see I want a categories path and the posts path as well. After you can see that I have an identifier for the type of category or type of post. This is known as a dynamic route.
What this really means is the FrontEnd doesn't necessarily know preemptively what the route will contain there. Hence the usage of the term dynamic. So what I am doing is encapsulating the value in what NextJS provides as a router variable, and I call that variable "category" or "slug". When I want to fetch the value stored all I have to do is leverage the withRouter HOC (higher order component) that NextJS provides us, and pluck the query paramater from the router object that gets passed as a prop by the withRouter HOC.
Here is a simplified example of the pages/categories/[category].js
and how I would utilize NextJS' withRouter HOC to retrieve the dynamic param value found at the route.
// Dependenciesimport React from 'react';import ReactDOM from 'react-dom';// Componentsimport { withRouter } from 'next/router';export class CategoryPage extends React.Component {render () {const { router = {} } = this.props;const { query = {} } = router;return (<div>Here is that category {query.category}</div>);}}export default withRouter(CategoryPage);
Not bad right! I love how organized this is, I can find all of my main views under that page's folder and all of the heavy liftings is done by NextJS.
Let's address the API folder as well found under pages. All files found under that folder are the endpoints I utilize throughout the app. Here's a quick example!
First, take a look at the files I have in the pages/api/*
folder.
First, take a look at the files I've got here, the implementation doesn't matter as much, just assume I exported an async function that fetches some data and returns the successfully retrieved data or has error handling.
Now observe how I utilize that endpoint. Notice that I reuse the exact path + filename for the query.
async componentDidMount () {const { router = {}, slug } = this.props;const pageViewsResponse = await fetch('/api/hitPageViews', {body: JSON.stringify({ slug, host: window.location.hostname }),headers: { 'Content-Type': 'application/json' },method: 'POST'});// ... more code here to utilize the response}
If you wanted to learn a bit more about how that works, here is where API routes are documented by NextJS.
Server-side Rendering
Now we get to SSR (Server-Side Rendering)With server-side rendering (SSR), the page HTML is generated on each request. This functionality is beneficial if you have an application that doesn't quite work for statically generated content. Most of the time, if the data in question updates frequently, server-side rendering could be of benefit. SSR offers faster load times for pages, benefitting both the user and web crawlers (leading to SEO improvements).
If you're unsure of when to use SSR-to quote NextJS docs, ask yourself the following:
If the answer is no, maybe use server-side rendering. If the answer is yes, static generation may be for you! The benefit to NextJS is that both options are equally available and easy to leverage.
Ok, so how does SSR work?
When a client requests the page, the server fetches the relevant data and generates the HTML using the data. Once all of this is complete the HTML gets sent back to the client. Client-side hydration of the javascript is the next and final step to allow for page interactivity.
How do we take advantage of SSR in NextJS? Easy!
export async function getServerSideProps(context) {return {props: {} // will be passed to the page component as props}}
Set up this handy function here, and NextJS will ensure that it gets invoked server-side at the request of the relevant page, or if the user navigated to the page client-side, NextJS will query the server through an API call. This API call subsequently invokes the same getServerSideProps
function. Just keep in mind, getServerSideProps only can be exported from a page. NextJS does the heavy lifting to enable SSR for you, just fetch the data you need in getServerSideProps, return it in an object within props and you're good to go!
Before I move on to the final topic of this article for NextJS, maybe you're thinking hey, she's missing something! I've seen getInitialProps
with NextJS, that works for SSR too! Yes, getInitialProps
is one more option for SSR but it can be deceptive. On initial page load, getInitialProps
will fetch your data server side, but if the user navigates client side to the page, getInitialProps
will not run to the server, rather it'll run client side. This is why I recommend if want true SSR without a mix of client side and server side handling, use getServerSideProps
.
SSG (Static Website Generator)
As mentioned earlier, NextJS allows us to build static pages or websites.
Bear in mind, I'm working on an article where I will go into more extensive detail on this section, given I used this functionality heavily for this blog!
My ByteSizedPieces blog is one perfect example of why we may want to build SSG based apps. Pages belonging to a blog tend to render static data, meaning it is not subject to change with high frequency. As a result of the nature of the data, we wouldn't need to leverage server side rendering. SSG is likely the way to go for blogs.
How does NextJS help us with SSG? Use getStaticProps
!
// ...Imports and such..export default function Posts({ posts = [] }) {return (<React.Fragment>{posts.map((post) => (<p>{post.title}</p>))}</React.Fragment>);}export async function getStaticProps() {return {props: {posts: await fetchPosts()}};}
With this code, fetchPosts will be invoked at build time and we've fulfilled the requirements for having a static web page with NextJS!
How does this work you might ask?
With SSG the page is already rendered in the server, waiting to be served to the client. This is better known as pre-rendering.
With SSR the page is setup on the server upon receival of a request.
Finally let's address one last detail. We know that with time, web apps need to evolve.
How about we create a scenario that demonstrates the power of NextJS?
Let's say you've created an app in which the majority of the pages are static. You now decide you want to incorporate users in the application. No worries here! NextJS allows us to mix client-side fetching with hooks like swr offers. If this option does not work for you, you may consider changing to utilize server-side rendering. NextJS allows us this flexibility of adaptation by offering these alternatives in-house as our apps naturally evolve over time.
This wraps up my summary of NextJS for now! When trying to find a framework or boilerplate setup I did not want to invest a lot of time learning a multitude of different solutions. I aim to become excellent at developing with one framework that offers me the versatile alternatives website developers can choose among when thinking about the next application requirements. Hopefully, you can see the power behind NextJS and decide to give it a try!
Until next time, happy coding!
Remember, developers are creatures that turn coffee into code. So I'd very much appreciate if you bought me a coffee! I’m a new writer and I will be posting very frequently on my findings and learnings in the tech industry and beyond. Join my newsletter if you would like to stay tuned!
Thanks for reading again! ❤️
Understand Open Graph Dynamic Image Meta Tags | 1 |
Pros and Cons of Caching Data in Software | 2 |
How to build a Modal in ReactJS (Part One) | 3 |