Creating a SSR site using Next JS and improving your development.
Tags: 101, redux, nextjs, serversiderendering
Published: 2022-10-14 18:40:20

---
title: Creating a SSR site using Next JS and improving your development.
published: true
date: 2020-03-23 19:58:53 UTC
tags: 101,redux,nextjs,serversiderendering
canonical_url: 
---

> Setup a development with NextJS is basically to follow the main guides of [https://nextjs.org/docs](https://nextjs.org/docs). However, setup it properly to have all the gadgets requires some experience struggling with it. This post will help you to leverage all this process.

_Contents:_

1. _Initial setup_
2. _CSS and SCSS_
3. _Basic Routing_
4. _Static files, handle svgs_
5. _Dynamic Routing_
6. _Redux_

**1. Initial Setup:**

To create a next project, we only need to create a folder and init a npm project:

```
mkdir best-ssr-ever
cd best-ssr-ever
npm init
```

Install NextJS packages and dependencies:

```
npm install next react react-dom
```

Add the following to package.json file:

{% gist https://gist.github.com/williamegomezo/52795bb56c2088b557a39bd0c6963e74 %}

Let’s test if everything is working, create a folder called  **pages** :

```
mkdir pages
```

Create a javascript file (the name of the file will be taken by NextJS as the route where the page will be set) and create a react component:

```
const Hello = () => <p>Hello NextJS!</p>;

export default Hello;
```

Install all dependencies:

```
npm i
```

Let’s run the dev server:

```
npm run dev
```

In the address **http://localhost:3000/hello** we should watch our first page in NextJS. Let’s create a component and import it in our page.

Create a folder called **components** and inside another one called  **cta** :

```
mkdir -p components/cta
```

Create a file called **index.js:**

{% gist https://gist.github.com/williamegomezo/d515102293245a1f0e50690b8b0a3833 %}

Let's import it in our hello page.

{% gist https://gist.github.com/williamegomezo/b0cde8185993a7c2671c62554a95db8f %}

So far we are good, but let’s improve our code:

**1.1. Config file.**

If our project scales, there will be a moment when the relative imports will be like the following ‘ **../../../../package.js’** and will be difficult to track or modify something, that’s why we will start configuring the absolute import:

In NextJS there is a config file that we need to create **next.config.js,** which allows us to have a custom configuration. In this file, we can change how long will last the caching, how will be called our **dist** folder, set additional webpack configuration and so on. Let’s customize our **webpack config** in order to have absolute import:

First, create **next.config.js** in the root directory of our project:

```
module.exports = {}
```

When we are working with webpack without NextJS, that is, we install webpack ourselves and create a **webpack.config.js,** to have a absolute import you must set the following:

{% gist https://gist.github.com/williamegomezo/de815ac0c9979311573ca49905333b06 %}

In NextJS, the json exported in **next.config.js** can have a field called **webpack** that will allow us to override default webpack config.

```
module.exports = {
    webpack: (config, options) => {
        // Here modify anything you need about the config.
        return config
    }
}
```

So, what we are going to do is to set the config in the following way:

{% gist https://gist.github.com/williamegomezo/44674e2ffff92e335b922a76f9102f09 %}

Setting that, we can now modify the import we had on **pages/hello.js**

```
import Cta from 'components/cta'
```

Run again npm run dev to see the changes in the browser.

Perfect, now you are much closer to have a perfect project setup.

Commit: [https://github.com/williamegomezo/creating-ssr-next-js/commit/1f5c4896aa5567da15edc16f1e97cdcfa7fa77a1](https://github.com/williamegomezo/creating-ssr-next-js/commit/1f5c4896aa5567da15edc16f1e97cdcfa7fa77a1)

**1.2. Linters!**

How did you bear a code without linters? Let’s install **eslint** to help us to set a standard linter configuration…

Run in the terminal:

```
npm install -g eslint

eslint --init
```

Select:

```
1. ❯ To check syntax, find problems, and enforce code style
2. ❯ JavaScript modules (import/export)
3. ❯ Vue.js ... kidding ❯ React
4. Does your project use TypeScript? ❯ Obviously not!
5. ❯ Browser
6. ❯ Use a popular style guide
7. ❯ Airbnb (https://github.com/airbnb/javascript)
8. ❯ JavaScript
9. ❯ (missing dependencies) ... install them with npm? ❯ Y
```

We will end with a  **.eslintrc.js** file in our root path.

If we have in vscode the eslint extension you will notice that the IDE will be warning us with every lint error.

There are some additions we should include in our  **.eslintrc.js** config, because we dont want to deal with them:

- ‘React’ must be in scope when using JSXeslint(react/react-in-jsx-scope)
- JSX not allowed in files with extension ‘.js’eslint(react/jsx-filename-extension)

So, let’s add to the file the following rules:

```
"rules": {    
    "react/react-in-jsx-scope": "off",
    "react/jsx-filename-extension": [1, { extensions: [".js", ".jsx"] }],
    "react/prop-types": [0],
    quotes: ["error", "double"],
    "arrow-parens": ["error", "as-needed"],
    "comma-dangle": ["error", "only-multiline"]
}
```

But, we will still have to set some settings to avoid warnings about absolute import and other react features, first install **babel-eslint** :

```
npm install eslint@4.x babel-eslint@8 --save-dev
```

Then add this to the  **.eslintrc.js** file:

```
"settings": {
    "import/resolver": {
        "node": {
            "paths": ["./"]
        }
    },
    "react": {
        "pragma": "React",
        "version": "16.9.0"
    }
},
"parser": "babel-eslint",
```

Almost ready, add in the globals the React field to avoid that **eslint** warns us about having React without importing, actually NextJS is importing it in background:

```
"globals": {
    "Atomics": 'readonly',
    "SharedArrayBuffer": 'readonly',
    "React": 'writable',
}
```

Out final .eslintrc will look in this way:

{% gist https://gist.github.com/williamegomezo/39be9520b65112d3e1a86913fcbecdb3 %}

If we run:

```
eslint .
```

We will see only warnings of our lack of seniority.

Commit: [https://github.com/williamegomezo/creating-ssr-next-js/commit/882cfa7f74ce85d0c613d1eb9c8160894dc4a5d6](https://github.com/williamegomezo/creating-ssr-next-js/commit/882cfa7f74ce85d0c613d1eb9c8160894dc4a5d6)

**2. CSS and SCSS configuration:**

Well, first, NextJS in its documentation shows a Built-in CSS support, which uses **styled-jsx** to isolated scoped CSS. This is the example provided by them:

```
function HelloWorld() {
    return (
        <div>
            Hello world
            <p>scoped!</p>
            <style jsx>{`
                p {
                    color: blue;
                }
                div {
                    background: red;
                }
                @media (max-width: 600px) {
                    div {
                        background: blue;
                    }
                }
             `}</style>
             <style global jsx>{`
                 body {
                     background: black;
                 }
             `}</style>
         </div>
    )
}

export default HelloWorld;
```

In this tutorial we are not going to use this, because I don’t like it :P and I prefer to have each file separated.

We will be using scss files, and for that we need a dependency: **next-sass**

We can find the package in the following link: [https://github.com/zeit/next-plugins/tree/master/packages/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass)

Its installation is really easy:

```
npm install --save [@zeit/next-sass](http://twitter.com/zeit/next-sass) node-sass
```

To use it we only need to wrap the exported json of **next.config.js** :

```
const withSass = require('[@zeit/next-sass](http://twitter.com/zeit/next-sass)')

module.exports = withSass({
    /* config options here */
})
```

I prefer to use an additional plugin called withPlugins, to start to add NextJS’s creators plugins. ([https://github.com/cyrilwanner/next-compose-plugins](https://github.com/cyrilwanner/next-compose-plugins))

```
npm install --save next-compose-plugins
```

This is the template provided by them:

```
const withPlugins = require('next-compose-plugins');

const nextConfig = {
  distDir: 'build',
  webpack: (config, options) => {

    // modify the `config` here

    return config;
  },
};

module.exports = withPlugins([
  // add plugins here..
], nextConfig);
```

Our config will look like this:

{% gist https://gist.github.com/williamegomezo/bb1661e23478beabde143511506fd52e %}

That is enough to style our cta:

Create in **components/cta/** a file **index.scss** :

components/cta/index.scss

{% gist https://gist.github.com/williamegomezo/ec47d66489d5df564be90f27f2a2aa1c %}

components/cta/index.js

{% gist https://gist.github.com/williamegomezo/efe8027730b65813b8d7c43e4fffc66b %}

Cool, now we can use scss. What if we use the cool CSS Modules?

Add field cssModules in **next.config.js**

```
module.exports = withSass({
    ...,
    cssModules: true
})
```

This can be done in withPlugins, adding a second element in the array of plugins, which is the options of the plugin:

{% gist https://gist.github.com/williamegomezo/1bb9ff417df7368513122026d11e8db0 %}

And change **components/cta/index.js** for:

{% gist https://gist.github.com/williamegomezo/f56c4a4081f5ba2d2c37b8250d11c68f %}

**css** is a map, with the name of the class in the scss and the hash name generated for CSS modules. Example:

```
{
    superCta: "oz3A60u9ZTGJI-7A1n1go"
}
```

In the browser we have:

```
<button class="oz3A60u9ZTGJI-7A1n1go">Click me</button>
```

There is a problem we haven’t tackle, what if we want global styles, like resets, colors, media queries?

One solution could be to install a new dependency: **sass-resources-loader**

```
npm install sass-resources-loader
```

And again, let’s add more rules to our **next.config.js** :

```
webpack: (config) => {
    ...

    config.module.rules.push({
        enforce: 'pre',
        test: /.scss$/,
        loader: 'sass-resources-loader',
        options: {
            resources: ['./styles/globals.scss'],
        },
    });

    return config;
}
```

Basically we are adding a rule, where it will look in a folder called **styles** (that we are going to create in the root folder) and it will look for a file called **globals.scss** (set the name you want, it could be **main.scss** )

There in **styles/globals.scss** you can import any file you want to have as a global resource in every page:

But be cautious, this tool must be used to declare **scss** variables, all css styles added in these global file will be repeated in each component and this will increase the final css file size and will slow the browser.

A better solution is to override **\_app.js** page. And set a custom App page that loads a **global.scss.** A basic example of \_app.js can be found here:  
[https://nextjs.org/docs/advanced-features/custom-app](https://nextjs.org/docs/advanced-features/custom-app)

The first thing we need to understand is that next does not render a React App but miracle, it has by default a file called \_app.js where the app is written, we can overload that document creating a file inside pages called \_app.js

Create a folder called **styles** and place there a **index.scss (or main.scss or globals.scss):**

{% gist https://gist.github.com/williamegomezo/4226ecc2ddfb6661d618d32d5ecd7c1c %}

Import it in  **\_app.js** :

{% gist https://gist.github.com/williamegomezo/b59fd725dcfd4813064310e4df2636f4 %}

Commit: [https://github.com/williamegomezo/creating-ssr-next-js/commit/b751a4c8c4c1d239aa4285f4a741cbc5b0b26616](https://github.com/williamegomezo/creating-ssr-next-js/commit/b751a4c8c4c1d239aa4285f4a741cbc5b0b26616)

**3. Routing:**

To make this more entertaining, let's create an app with purpose.

Let’s create the Tour of Heroes of our enemy! ([https://moynokylxexp.angular.stackblitz.io/dashboard](https://moynokylxexp.angular.stackblitz.io/dashboard))

So, we have to create three pages:

- /dashboard
- /heroes
- /detail/:id

We will let the third one for the step of dynamic routing

Create two js files in the folder **pages** : **dashboard.js** and **heroes.js**

pages/dashboard.js

{% gist https://gist.github.com/williamegomezo/e3cae3fd5c132ec0c406005a003c1649 %}

pages/heroes.js

{% gist https://gist.github.com/williamegomezo/283c19b0378bccda1f5eac69f08f40d8 %}

Check the routing visiting:

- [http://localhost:3000/dashboard](http://localhost:3000/dashboard)
- [http://localhost:3000/heroes](http://localhost:3000/heroes)

Well, now, how can we go from one page to another?

Let’s modify our Cta component to have the Link component of NextJS:

components/cta/index.js

{% gist https://gist.github.com/williamegomezo/a110695c041872b71a6d6b25583525c7 %}

We add Link from “next/link” which allows as to having a kind of SPA routing in a SSR app.

Let’s modify our pages:

pages/dashboard.js

{% gist https://gist.github.com/williamegomezo/8eee0dce7c5faa096dc894059b1fdd0d %}

pages/heroes.js

{% gist https://gist.github.com/williamegomezo/0fcd9a11b11c6949ba30b6f16c798721 %}

Our Cta looks ugly, I will add some styles to it.

```
.superCta {
    display: inline-block;
    background-color: white;
    color: black;
    font-family: 'Roboto';
    font-weight: 500;
    font-size: 20px;
    border: 1px solid;
    text-decoration: none;
    padding: 10px;
    margin: 10px;
} 
```

Commit: [https://github.com/williamegomezo/creating-ssr-next-js/commit/f58f5983556761aa94a5876b12fc3d2335b671a3](https://github.com/williamegomezo/creating-ssr-next-js/commit/f58f5983556761aa94a5876b12fc3d2335b671a3)

**4. Static files:**

Handling static files is easy, you must create only one folder: public, there you put any assets you want.

Let’s download an image: [https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/React.svg/1200px-React.svg.png](https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/React.svg/1200px-React.svg.png)

And put in  **./public/images/react.png**

Remember our **hello**  page?

pages/hello.js

{% gist https://gist.github.com/williamegomezo/33b963b30f3fc4de9c23e925346bf389 %}

There is also another way to handle static files and is importing then, and using libraries to load them:

SVGs: Dependencies everywhere: Let’s install svg-react-loader

npm install svg-react-loader

Again we have to modify our webpack config, adding the following rule:

```
config.module.rules.push(
    {
        test: /\.svg$/,
        exclude: /node_modules/,
        loader: 'svg-react-loader',
    },
);
```

Go to material icons: [https://material.io/resources/icons/?search=search&style=baseline](https://material.io/resources/icons/?search=search&style=baseline)

And look for **search** , save the icon in the folder **/static/icons/**.

Now, let’s load it. But first, let’s create another component, a search bar:

components/searchBar/index.js

```
function SearchBar(props) {
     const { placeholder } = props;

     return (
         <div>
         // Here there should be a search icon
         <input placeholder={placeholder} />
         </div>
     );
}

export default SearchBar;
```

Now let’s add the svg:

```
import SearchIcon from 'public/icons/search.svg';
```

And …

{% gist https://gist.github.com/williamegomezo/8edbf838b62f46eb365667b20ec49324 %}

Adding it the to dashboard:

It would be better to wrap **SearchIcon** in a component maybe called **SvgIcon** and load dynamically the svg based on a prop. That will be done creating:

components/svgIcon/index.js

{% gist https://gist.github.com/williamegomezo/7061776d5ecb07b83d0f7794d7df7353 %}

components/searchBar/index.js

{% gist https://gist.github.com/williamegomezo/2f0f46f908f55e703f164d418d960c2f %}

I will add some styles to the searchBar:

components/searchBar/index.scss

{% gist https://gist.github.com/williamegomezo/23bb76fff535d511f63caea615523730 %}

{% gist https://gist.github.com/williamegomezo/01d8319340dd69c5276de2b34f41205f %}

Well, in order to have heroes, for now we will mock them:

public/mocks/heroes.json

{% gist https://gist.github.com/williamegomezo/61238a79a9ae86ea78996251409185fe %}

Now, we know that the heroes will be on the route localhost:3000/mocks/heroes.json, obviously we can import them, but there is more fun if we fetch them, I will use the love of my live which is called axios, let's install it:

```
npm install axios
```

Now, let’s use a functionality of NextJS that allow us to get an initial status of the page: getInitialProps

Our dashboard will look like:

pages/dashboad.js

{% gist https://gist.github.com/williamegomezo/5516a2cb9b1415d1b288bab6c718d31d %}

For now, our search bar does not work, let’s wait to redux part to make it work.

But let’s create better a List component in order to have routing to the profile page of each hero.

components/List/index.js

{% gist https://gist.github.com/williamegomezo/21737702c03dc131994f1eaef0c4a676 %}

As you can see we use our component Cta, so we can go to the profile of each Hero, to do that we need dynamic routing.

Commit: [https://github.com/williamegomezo/creating-ssr-next-js/commit/8e29df076cb5330238939a4cbecaabaf0e445021](https://github.com/williamegomezo/creating-ssr-next-js/commit/8e29df076cb5330238939a4cbecaabaf0e445021)

**5. Dynamic routing:**

Let’s create a folder inside **pages** called **heroes** and create a js file called **[hero].js**

pages/heroes/[hero].js

{% gist https://gist.github.com/williamegomezo/7cbc52e8e0209a173e59c06dd23f0893 %}

Note that we use a module of NextJS called useRouter, with this we can get an instance of the router and get the query parameters in the url, in this case the query parameter is what follows after **heroes/** and Next looks if there is a js file in the folder **heroes** with parameters in its name (**[hero].j**s, that is how **hero** becomes an argument int he query)

**6. Redux:**

I want to present you an example of how using redux and connect the components, to be honest this app is pretty simple to use Redux but this is for academic purposes.

Before starting let’s do it in the simple way, lets send a callback from the **dashboard** page to the **searchBar** in that way the can alter heroes array using the onChange of the **searchBar**

components/searchBar/index.js

{% gist https://gist.github.com/williamegomezo/6a2ca6e3cc234df41d2581bc1950633b %}

Note that now SearchBar has a new prop, which is called filterUsingValue and this is just a function of the **dashboard.js** file that is sent as prop. Now we can execute that function a pass to is a value, the value of the input.

pages/dashboard.js

{% gist https://gist.github.com/williamegomezo/a3114e08d7ccc2735e2bc4db086deeb4 %}

Note that we convert the page component into a React.component in order to use the state of the component and mutate it using this.setState with the function filterHeroes, note that this function is the one that is sent to the searchBar, so the search is in charge of call this function setting the value of the input.

Now let’s try the same but using Redux.

To use Redux, we need to do some tricky stuffs, sorry but everything has its cost.

Install the dependencies:

```
npm install redux react-redux next-redux-wrapper --save
```

Let’s first create a folder called store, in this folder we will set two folders actions and reducers, in actions we will create the regular Redux actions types and actions:

store/actions/action-types.js

```
export const CHANGE_SEARCH = 'CHANGE_SEARCH';
```

store/actions/index.js

{% gist https://gist.github.com/williamegomezo/f7c6630c7c9d2dbf774b5b16773fb575 %}

In reducers we will create a Redux reducer to change the state:

store/reducers/searchReducer.js

{% gist https://gist.github.com/williamegomezo/e5cfacf181327b0db7fbb789d88903fa %}

Finally, we will create the store in store/index.js

{% gist https://gist.github.com/williamegomezo/dfa3632727fd9c6cdede13e98d500c46 %}

Note that makeStore must be a function, because the wrapper we will use it require to create the store in this way.

Now, we have Redux as we would configure it in Create-React-App. Let’s modify \_app.js in order to import the store and set the Provider.

pages/\_app.js

{% gist https://gist.github.com/williamegomezo/ab6d811938159d40202fcef142f1cacc %}

As our pages are going to use getInitialProps we need to call it from **\_app.js getInitialProps**.

Let’s add the dispatch in the SearchBar component to give it the ability of change the state.

components/searchBar/index.js

{% gist https://gist.github.com/williamegomezo/1800afffaa92b0cad1df6bf47a5f9539 %}

Note that we change from function component to React.Component to prettify a little bit the code and keep the component as a class. Using connect when we are exporting the component the dispatch function is set in the props of the component. That’s why in the constructor the dispatch is got from the props. Using dispatch and the action from the actions we can alter the state.

Now is time to refactor pages/dashboard.js

{% gist https://gist.github.com/williamegomezo/54e39e54e76f0b95dc0de3c5a031f74b %}

Note that now we dont need to pass a function to the searchBar component, we have decoupled it. Now the state of the reducer is in the property search and we can filter the list each time the props are updated in the render function.

Commit: [https://github.com/williamegomezo/creating-ssr-next-js/commit/eea82b221537b358b7dba27603bc71598f3f9571](https://github.com/williamegomezo/creating-ssr-next-js/commit/eea82b221537b358b7dba27603bc71598f3f9571)