πŸ”–

Style Guides, Practices & Methodologies

This will include practices with other popular packages as well. Since NextJS really isn't your out-of-the-box React it will take some maneuvering to set up some things which need to work smoothly with SSR pages.

Disclaimer : Please come here after going through the docs at least briefly.

TOC

Project Structure Example

Paths

Create a jsconfig.js file for this. Have aliases for the paths so nesting imports don't occur.

Your imports will be much cleaner and it's easy to move files or change names as everything is absolute.

Image optimization

If you are under the assumption that Next Images cannot optimize images dynamically, you're mistaken, we can optimize images coming from FE S3 or even S3 links which are attached from an API.

We will have to do the following inside next.config.js β†’

You can read more about it here.

Environment variables

This is going to be a mixed bag. You can handle this in two ways :

  • In next.config.js itself -

We can see here there's just a lot of unnecessary things going on along with the fact β†’ Even sensitive keys are exposed and in the codebase itself.

  • Look into creating the normal .env.local file and having your keys there. There are some guidelines which you can check here.
    • If you are having CI/CD processes, try to come up with an encryption flow for the env keys. We have this documented here for Unschool.

Authentication

There would be some situation for authenticated pages or in general a lot of logic required from an SSR function on the server. To keep things organized always return the response from a separate file like ssr.js

  • For cookies, we handle the logic on server-side as well. One more thing you can leverage is β†’ If you're using SSR, keep in mind you can opt-in for server side cookies!
    • This is much more secure as it's HTTP only and avoids XSS attacks.
    • We can easily do this by writing some Node.js code inside our /api folder.
    • Login :
    • Logout :
  • Keep in mind to secure the /api pages as anyone can access them. You can have a hex key here to protect it and redirect it to a 403 if the key isn't passed while making the request.
  • From the FE you can just hit the end-point β†’ /api/login using fetch, if you want to use the login and logout actions on the server itself, then use a package called isomorphic-unfetch.

Dynamic Imports

There will be situations when using some packages or even Font Awesome Kits, where there will be a mismatch of rendered HTML on the client-side vs server-side.

Example :

This is mostly because the package is not designed or coded to render the right HTML code on the server-side but it renders correctly on the client-side.

For these situations + for a situation where you know you can import components / packages only when needed β†’ You can use Dynamic imports.

  • For the server-side mismatch errors, please include ssr: false while dynamically importing components.

Router Loading times

We will have to keep in mind if you're using SSR with all page queries on the server-side, yes there will be no loading screens needed, but let's say you want to go from one authenticated page to another, where both have page queries and some logics β†’ This will take some time on the first load.

  • From the second load, depending on which GraphQL client you are using β†’ Say for example Apollo GraphQL which supports server-side GraphQL queries, these will get cached.
  • On redirecting or going to another route, Next JS will handle this by staying on the current page whilst it makes the queries and loads the new page, then redirects, very similar to blocking mode present in other data fetching methods.
  • It is around 1-1.5 seconds. For this, we would need to handle it properly as it can be a bad UX.
    • Handle this by listening to Router events on the _app.js file. By Router, I mean from next/router
    • Have a progress bar on the top of the page. You can use a good library called nprogress for this.

GraphQL Clients

As mentioned in the Starter Guide, this can be of two ways. We are going to see the Apollo client as it is more complex with SSR queries.

  • Caching, the main thing we want here is server-side queries and client-side queries to be cached.
  • Before looking into the code below, understand the below code solves the issue of β†’ Setting Authentication headers when executing queries from the server-side.
    • We have to keep in mind the server doesn't have access to local storage or redux or any of these things.

An example query would be β†’

  • This function gets used in getServerSideProps, please check Authentication.