AnanyaGB
/
Blogs
NextJS 13 Dynamic Routing
A comprehensive guide to the NextJS 13 dynamic routing, with SSG.
Blogged on
Sep 2, 2023
Article Prop.
1248 words
7 min read

NextJS 13 introduces an app router. This brings forth many new features such as a layout for each sub-directory and a loading state integrated with the app router. With NextJS 13 you can create async default export for your pages; and yes you aren't dreaming. This post aims to create a complete summarized version of SSR dynamic routing, like this blog site.

Some FAQs

  • What is SSG?: SSG stands for Static Site Generation. Usually used for speed and performance, SSG is used to create sites which have static data like blog site.

  • What is async?: async is a keyword in JavaScript. async is used to create function that returns a promise. async is usually used with await, which is used to make a function wait for a promise.

Getting started

Next 13 introduces us to the app router. The App Router is a new paradigm for building applications using React's latest features. If you're already familiar with Next.js, you'll find that the App Router is a natural evolution of the existing file-system based router in the Pages Router. Learn more about the app router.

Installing base project

The best way to create a NextJS Project is by using the official create-next-app package.

If you do not have the above package, run the following command, which will install the create-next-app package globally.

$ npm install -g create-next-app@latest

Once you've installed the create-next-app package, run the following command. This will create a base NextJS project.

$ npx create-next-app my-ssg-site

There will be certain options available. Make sure you select the following:

  • Do you wish to use the /src directory? No (should be selected by default).
  • For other options, use the default selection.

Open my-ssg-site in an IDE. If you use VSCode, run:

code my-ssg-site

Take a nice look at the directory tree. You should see the following structure:

> app
    | favicon.ico
    | globals.css
    | layout.js
    | page.js
> node_modules
    > ... packages
> public
    | next.svg
    | vercel.svg
| .eslintrc.json
| jsconfig.json
| next.config.js
| package-lock.json
| package.json
| postcss.config.js
| README.md
| tailwind.config.js

This is the new directory structure introduced in the app router in NextJS 13. This is a game changer, as I will be pointing out in upcoming blogs.

Now that you have your base project installed, we can move forward doing some real stuff.

Fire up the local server by running the following command, and go to http://localhost:3000.

$ npm run dev

Dynamic route segments

As, the name suggests, dynamic routes are used to create routes from dynamic data. Dynamic Segments are used, that are filled in at request time, or, prerendered at build time.

Convention

As per NextJS official documentation, a Dynamic Segment can be created by wrapping a folder's name in square brackerts: [folderName]. For example, [id] or [slug].

Dynamic Segments are passed as the params prop to layout, page, route, and generateMetadata functions.

Example

Take for example, this very blog. Currently you are in the pathname /blogs/nextjs-13-dynamic-routing. This at the source-code side is present as /blogs/[slug]/page.js, where [slug] is the Dynamic Segment for blog posts.

Head over to your base project, and, create a blogs folder inside the app directory. Inside the blogs folder, create a [slug] folder. And inside the [slug] folder, create a page.js file.

Add the following code to the page.js file:

export default function Page({ params }) {
  return <div>My Post: {params.slug}</div>;
}

Once done, you should be able to see the following in your browser:

🎉 Congratulations! You've created a Dynamic Segment. But this Dynamic Segment will only be called on request, i.e., only when user visits the url. No static sites will be created during build time. Therefore, dynamic routes based on requests will affect the performance of your app greatly.

In order to overcome this problem, generateStaticParams function is used.

Introducing gSP

Now before we start, you must be wondering what is gSP?

gSP is an abbreviation I made for generateStaticParams function. Is this an official abbreviation? No 😤. Will I be using this abbreviation further in the blog? No 😤. Then, why did I use it in the heading? Because, generateStaticParams is too big to fit in the heading in mobile devices 💅.

The generateStaticParams function can be used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time, thus, improving performance.

Let's say we have the following data of blog posts, under an array named postsData.

const postsData = [
  {
    slug: "first-post",
  },
  {
    slug: "second-post",
  },
  {
    slug: "third-post",
  }
]

As per the above data, there are three blog posts. So our app should aslo have three blog posts under the /blogs/ directory, dynamized by [slug].

In order to achieve the three routes during build-time, rather than on request, we use generateStaticParams function.

Update the contents of the /blog/[slug]/page.js file, as per the following:

export const generateStaticParams = async () => {
  return postsData.map((post) => ({
    slug: post.slug,
  }));
};

export default function Blog({ params }) {
  const { slug } = params;
  return <div>Post name: {slug}</div>;
}

Now if you run different segments, you will see the same thing as before, as:

What's the difference then? Well, this time, we have used the generateStaticParams function. As a result, the paths were generated during build time, rather than on request.

Let's assume, user goes to a fourth-post path. Now, fourth-post was not available in the post data. Yet if you visit the fourth-post path, under /blogs/fourth-post, the page will load, as if there is nothing wrong with our code. Well, technically there isin't.

You see, the three posts available in the data, first-post, second-post, third-post, which were passed through the generateStaticParams function, were built statically during build time. When one goes to the fourth-post path, the page is loaded upon request, i.e., the fourth-post was requested dynamically outside your data.

In order to prevent loading dynamic routes on request, i.e., loading dynamic routes outside your known data, we use dynamicParams segment config option, to control what happens when a dynamic segment is visited that was not generated with the generateStaticParams function.

In the /blogs/[slug]/page.js, add the following:

export const dynamicParams = false;

Now if you visit /blogs/fourth-post, a 404 error will be returned.

If you want to load pages that was not generated with the generateStaticParams function during build time, change the value to true.


This is how you can create Dynamic Segments in NextJS 13. The function generateStaticParams is used in the app router, and replaces the getStaticPaths used in the pages router in earlier versions of NextJS.

In the next post, I'll create a detailed tutorial on creating a basic blog site, without nested posts. In a even later post, I'll use the Catch-all Dynamic Segments in order to create a blog site, with nested posts.

Wait... I can create blog sites with nested posts? Yes, I can. So this site has nested posts? No, this doesn't because, I plan on creating a separate directory /tutorials, for nested posts, which will usually be tutorials.

Following are the links that could prove helpful for further reading:

Thanks for reading the blog post. Over and out!