DEV Community

Cover image for Complete setup of Nextjs, SWR , Axios and Material UI with SSR for your upcomming projects
Harsh Mangalam
Harsh Mangalam

Posted on

Complete setup of Nextjs, SWR , Axios and Material UI with SSR for your upcomming projects

Hello Community,

In this trending world Reactjs is a perfect library for making user interfaces.
But we knew if we want better SEO,SSR, better Image optimisation, Code splitting etc we have better one Nextjs which is build on top of Reactjs for production.

Material ui is a reactjs based material component library mainly focused on providing awesome and mind blowing design system for web apps.

When we work on frontend project we have to care about caching because we make api request to another server for the purpose of getting data.SWR is a strategy to first return the data from cache then send the fetch request and finally come with the up-to-date data.

Axios is used for making api call to our server. You can use Axios for your both client side and server side (getServerSideProps and getStaticProps) hence it is easy and relevant for api request

Library and Framework we will using

  1. Nextjs
  2. SWR
  3. Axios
  4. Material UI

Lets jump to setup

Initialize a new brand nextjs project

npx create-next-app

Enter fullscreen mode Exit fullscreen mode

Installing dependencies

yarn add axios swr @material-ui/core @material-ui/icons

Enter fullscreen mode Exit fullscreen mode

src/pages/_app.js


import React from "react"
import { ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import theme from "../theme";
import Navbar from "../components/Header/Navbar";
import Footer from "../components/Footer/Footer";

import Axios from "axios";
import { SWRConfig } from "swr";

import { colors, Container, makeStyles } from "@material-ui/core";

Axios.defaults.baseURL = process.env.NEXT_PUBLIC_SERVER_BASE_URL + "/api";
Axios.defaults.withCredentials = true;

const fetcher = async (url) => {
  try {
    const res = await Axios.get(url);
    return res.data;
  } catch (err) {
    throw err.response.data;
  }
};

const useStyles = makeStyles((theme) => ({
  main: {
    flex: 1,
    padding: "16px 0px",
  },
}));

export default function App() {
  const classes = useStyles();
  const { Component, pageProps } = props;

  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);

  return (
    <React.Fragment>
      <SWRConfig
        value={{
          fetcher,
          dedupingInterval: 10000,
        }}
      >

            <ThemeProvider theme={theme}>
              <CssBaseline />
              <div
                style={{
                  display: "flex",
                  flexDirection: "column",
                  justifyContent: "space-between",
                  minHeight: "100vh",
                  backgroundColor: colors.grey[200],
                }}
              >
                <nav>
                  <Navbar />
                </nav>

                <main className={classes.main}>
                  <Container>
                    <Component {...pageProps} />

                  </Container>
                </main>

                <footer>
                  <Footer />
                </footer>


              </div>
            </ThemeProvider>

      </SWRConfig>
    </React.Fragment>
  );
}

Enter fullscreen mode Exit fullscreen mode

src/theme.js



import { createMuiTheme } from "@material-ui/core/styles";

// Create a theme instance.
const theme = createMuiTheme({
    palette:{
        type:"dark"
    }
});

export default theme;

Enter fullscreen mode Exit fullscreen mode

src/pages/_document.js


import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheets } from "@material-ui/core/styles";
import theme from "../theme";

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          {/* PWA primary color */}
          <meta name="theme-color" content={theme.palette.primary.main} />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
  // Resolution order
  //
  // On the server:
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. document.getInitialProps
  // 4. app.render
  // 5. page.render
  // 6. document.render
  //
  // On the server with error:
  // 1. document.getInitialProps
  // 2. app.render
  // 3. page.render
  // 4. document.render
  //
  // On the client
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. app.render
  // 4. page.render

  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
    });

  const initialProps = await Document.getInitialProps(ctx);

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [
      ...React.Children.toArray(initialProps.styles),
      sheets.getStyleElement(),
    ],
  };
};


Enter fullscreen mode Exit fullscreen mode

Lets do some best practices with ssr and swr together


import Head from "next/head";
import axios from "axios";
import useSWR from "swr";
import Categorycard from "../components/Category/Categorycard"
import CategoryLoading from "../components/Category/CategoryLoading"

export default function Home({ categories }) {
const {data,error} = useSWR("/categories",{initialData:categories})
  return (
    <div>
      <Head>
        <title>Categories</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <div>
        {/*loop through category list using `data`    */}
        {!data ? <CategoryLoading /> : data.categories.map(category=>(
<div key={category._id}>
<CategoryCard category={category}  />
</div>
))}
      </div>
    </div>
  );
}
export const getServerSideProps = async () => {
  try {
    const res = await axios.get("/categories");

    return {
      props: {
        categories: res.data,
      },
    };
  } catch (error) {
    console.log(error);
  }
};


Enter fullscreen mode Exit fullscreen mode

Good luck for your next project..

Oldest comments (1)

Collapse
 
minhhunghuynh1106 profile image
igdev

Is SWR good for SEO? When I view page source it doesn't have any content