These three functions combine two topics, component props, and pre-rendering.
Props can be used to pass values to a component, and you can find out more about that here. Since in Next.js pages are also components, we can pass values to them as well! The three “getXProps” functions each represent slightly different methods of passing props to a page.
We’ll explore each of these in more detail with an example, but the shortened version is getInitialProps uses Server-Side Rendering, but has been replaced by getServerSideProps which uses the same, and getStaticProps uses Static Site Generation.
Pre-rendering is producing the HTML for our web app before we send it to the client. In a regular JavaScript web app like React, we start off with a basic HTML placeholder page, and JavaScript is then used to render the rest of the HTML.
Next.js provides two different techniques that allow it to pre-render the HTML for your web app, sending as little JavaScript to the client as possible to help with performance. These two techniques are Server-Side Rendering, or SSR, and Static Site Generation, or SSG.
If you’re not already familiar with Next.js, it’s a great framework that expands on React, and provides some really useful additional functionalities, and you can read more about it here.
getInitialProps
getInitialProps is used to enable Server-Side Rendering, or SSR for a page. With SSR, the HTML is generated on the server when it needs to be served up to the client.
On the first load, it will run on the server, and on every subsequent run it will run on the client. This can be useful for fetching data you expect to be changing often, like the latest posts on a social media page.
const Initial = ({ cat }) => {
return (
<div>
<h1>Random Cat:</h1>
<Image src={cat} layout="fixed" width="250" height="250"></Image>
</div>
);
};
Initial.getInitialProps = async (ctx) => {
const { data } = await axios.get('https://cataas.com/cat?json=true');
return { cat: 'https://cataas.com' + data.url + '?type=sq' };
};
export default Initial;
In this example, we use getInitialProps to perform a get request. If you’re unfamiliar with making API requests in Next.js or vanilla React, I recommend checking out this page we have as an introduction.
It’s strongly recommended to use one of the other two functions instead of this one, and if you need a direct parallel, it would be getServerSideProps.
You might notice here we’re using the Image component from Next.js instead of just an img element. There’s a few benefits to that that you can find here.
getServerSideProps
Like getInitialProps, getServerSideProps will run on the server. Unlike getInitialProps however, it will always run on the server.
getInitialProps is being deprecated instead of this function, the main reason being to give you greater control over where the code is ran. getServerSideProps is guaranteed to run on the server, and you can even use server-side only code, like the fs module to load files to pass as props.
Here’s the example above rewritten to use getServerSideProps:
const ServerSide = ({ cat }) => {
return (
<div>
<h1>Random Cat:</h1>
<Image src={cat} layout="fixed" width="250" height="250"></Image>
</div>
);
};
export async function getServerSideProps() {
const { data } = await axios.get('https://cataas.com/cat?json=true');
return {
props: { cat: 'https://cataas.com' + data.url + '?type=sq' }, // will be passed to the page component as props
};
}
export default ServerSide;
getStaticProps
getStaticProps is slightly different to the previous two functions.
In Static Generation, we try to generate as much of the HTML for the website as possible when you build your app. This means if data is going to change often, you cannot use this function, as it won’t change after you deploy your app.
This makes it useful for something like a blog post, where the content won’t change. The benefit you gain from this is performance; nothing needs to be fetched or evaluated on the client or server-side; the server just serves the raw HTML for the page. Like getServerSideProps you can also use server-side only code in your app.
You can combine this with dynamic routing in Next.js. If your page is a dynamic route, e.g. site.com/blog-posts/[postId].jsx, any time you access a path like blog-posts/7, it will be routed to the same page and Next.js will pass the value to the router accessible through router.query on useRouter().
With a static site however, we need to have every HTML file generated already so we can just serve the HTML file, so how does this work when you have a dynamic path?
This is what getStaticPaths solves. You can use whatever method you wish to generate all of the possible paths you want Next.js to build a static page for. This might be something like the paths for all of the blog posts you have and their ids.
Here’s an example using getStaticProps and getStaticPaths to load blog posts locally from text files:
import fs from 'fs'; //This will get removed on the client
import path from 'path';
const Static = ({ blogPost }) => {
return <div>{blogPost}</div>;
};
export async function getStaticProps({ params }) {
//We get the filename as a parameter from the context object
//fs is server side only, but this code only runs on the server
const blogPost = fs.readFileSync(
path.join(
process.cwd(),
'src/pages/examples/blog-posts',
params.staticBlogPostId + '.txt'
),
'utf8'
);
return {
props: { blogPost }, // will be passed to the page component as props
};
}
export async function getStaticPaths() {
//I have a folder containing blog posts in text files
const paths = fs
.readdirSync(path.join(process.cwd(), 'src/pages/examples/blog-posts'))
.map((fileName) => fileName.split('.')[0]); //Just a quick map to remove the .txt from the filenames
console.log(paths); //[ 'manchester-holiday', 'new-beginnings', 'new-job' ]
return {
paths: paths.map((fileName) => {
return { params: { staticBlogPostId: fileName } };
}),
fallback: false, //Means anything else will 404
};
}
export default Static;
The actual component is small, just outputting the text recieved, but the pre-rendering is the more interesting part:
- In getStaticPaths we get a list of the files in a directory; all our blog posts in this case.
- Our getStaticProps function gets used to generate the page for each of our blog posts, by simply loading the blog post from a text file
- The contents of the file gets passed to the page as props
- All this happens on the server; from the client’s point of view you just get a HTML page with the blog content!
tl;dr:
- don’t use getInitialProps, it has been replaced by getServerSideProps, but consider if you can use getStaticProps
- getStaticProps is for Static Site Generation, use that when you know what data you’re fetching at build time, e.g. a blog post, very fast performance and good SEO
- use getServerSideProps for Server-Side Rendering, use that when you have data that might be changing often, e.g. a weather API, but the performance may be slightly worse than SSG
And that’s it! Hopefully that made sense, and these examples are helpful enough to inspire you to use these in your own projects. I’d love to see any smart ways that you’ve optimised your website with pre-rendering, so feel free to share them in the comments below! Feel free to comment as well if anything was confusing, or if you have any questions, or if you simply enjoyed the article!
💬 Leave a comment