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.
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.
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.
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:
/src
directory? No (should be selected by default).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
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.
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.
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.
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:
generateStaticParams
api reference: Official NextJS documentation.Thanks for reading the blog post. Over and out!