Among the changes included with Next.js v9.3 was the introduction of getServerSideProps
. When it came to defining props for pages rendered on the server side, getServerSideProps
essentially replaced getInitialProps
.
Nowadays, some developers occasionally run into confusion about which method to use. In this article, we’ll explore how getServerSideProps
and getInitialProps
work, reviewing an example for each. Let’s get started!
Inner workings of getServerSideProps
and getStaticProps
Essentially, if you need to render a page at build time before making any request, then you’d use getStaticProps
. getStaticProps
will mark the page to be statically rendered, meaning it won’t re-render until the next build. While this methodology is great for speed and SEO, it isn’t great for dynamic data that changes regularly.
If you want to render a page at the time of the request, you can use getServerSideProps
to render a page on the server before responding to a request. getServerSideProps
will mark the page to be rendered on each request. In this method, the server will have to build the page every time, which can slow down the entire process. However, this methodology still offers SEO benefits over using plain Vanilla React, which would render your content on the client.
The thing about updates to languages and frameworks is that backward compatibility matters. Even if old patterns and methods are no longer needed for future projects, they are still maintained to avoid breaking legacy code and for the occasional edge cases. This is the case of getInitialProps
, which behaves almost identical to getServerSideProps
.
Is there a difference between getInitialProps
and getServerSideProps
?
The main difference between the legacy getInitialProps
and the newer getServerSideProps
is how the function is used during transitions, when users click on a Link
to visit different parts of your site.
With getInitialProps
, the transition will execute server-side on the initial page load, but then execute on the client during page transitions. However, if the logic refers to things like databases, which may not be accessible on the client, this can create issues.
For example, in the code snippet below, the fetch
of the users directly from the database would work on the initial page load. However, it may fail on transitions since the User
model would not be available on the client.
As a solution, we could use Next.js API endpoints. However, this is a less efficient method than directly accessing the database on the server side:
// Import a User model import User from "../models/User" function Page({ User }) { return <div>Username: {User.username}</div> } Page.getInitialProps = async (ctx) => { // Get user id const User = await User.findOne(ctx.query.id) // return props return { User } } export default Page
On the other hand, getServerSideProps
will execute the transitions server-side on the initial page load. On the page transition, getServerSideProps
will make an API call to the server, running the logic again on the server and returning the results as JSON.
By making this change, we fix the problem of context switching that occurs with getInitialProps
. In the example below, you can make a direct call to the database, and it will work fine on initial page load and on transitions:
// Import a User model import User from "../models/User" function Page({ User }) { return <div>Username: {User.username}</div> } export async function getServerSideProps(context) { // Get user id const User = await User.findOne(ctx.query.id) return { props: {User}, // will be passed to the page component as props } } export default Page
Which one should you use?
If you’re creating newer Next.js applications, there is probably no reason to use legacy methods like getInitialProps
because getServerSideProps
and getStaticProps
provide better functionality and semantics.
In this article, we clarified the differences between getServerSideProps
and getInitialProps
, looking at an example of how we can solve context switching in getInitialProps
with getServerSideProps
.
I hope you enjoyed this article, and if you have any questions, please leave a comment. To learn more about Next.js and other meta frameworks, be sure to check out this article comparing Next.js and Remix.
I like the article
have one question how we can make api call in _app.js to get the data and pass over nav component
is this api call to a third party api or to one of the endpoints from the next app? Generally, unless the change is happening after the particular page loads (like data that relies on user input before making api call) I would just use getSeverSideProps or getStaticProps to make database calls instead of calling API endpoints.
yes …
I like this article and know I can understand the difference between getInitialProps & getServerSideProps
This is an older post, but I feel like Vercel/Next.js have done a pretty admirable job obscuring the valid reasons to still use getInitialProps. Even a lot of seasoned devs may not be aware that the original workflow most people used in earlier isomorphic/universal react apps pretty much assumed you had a separate and decoupled API. Its endpoints would be called from both client (navigation changes) and server (initial load or full browser refresh) using the same code via something like isomorphic fetch or axios.
There are both advantages and disadvantages to this pattern:
1. Your backend isn’t limited to Javascript/Typescript, it can be any language. Being decoupled, it’s easier when you have frontend/backend specialists.
2. If you have a mobile app, IoT or anything else besides a web browser a decoupled API is going to save a lot of time. These things don’t share a view layer but probably do share a data source.
While you can of course call a decoupled API endpoint in getServersideProps, it’s probably a bad idea because it adds an extra network hop when called from the client. Using the older pattern (getInitialProps in Next), you would be calling the final endpoint directly instead of “asking” the Next.js backend to do it.
3. getServersideProps as far as I know results in more requests to your server. getInitialProps can be cached, but from the documentation it seems that GSSP is always called on route changes even when the data was recently received and still valid.
The disadvantages are pretty well documented, but mostly avoidable if you know what you’re doing, (don’t import server only packages from isomorphic code, check for client when using browser APIs, etc).
This is not a recommendation to use getInitialProps. It is cleaner and easier to use the newer patterns for a lot of apps. They reduce complexities, but they also introduce others. There are plenty of people who will probably just choose a different framework now that Next doesn’t seem to want to support their use case.
These are experimental times for SSR/SPA fusion… IMO the newest patterns of islands and server components are an actual reason to be excited. It’s a bit of a mess ATM, but it will be interesting to see what it looks like once the dust settles.