You've successfully subscribed to Smartcodehub ™ Blog
Great! Next, complete checkout for full access to Smartcodehub ™ Blog
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
Next.js | react server side rendering Framework

Next.js | react server side rendering Framework

Neeraj Dana
Neeraj Dana

Next.js | react server side rendering Framework : As we all know that react is a very popular ui library for creating blazing fast web apps and even mobile apps .

The Benefits of Server-Side Rendering

SEO might be the conversation that starts your team talking about server-side rendering, but it’s not the only potential benefit.

Here’s the big one: server-side rendering displays pages faster. With server-side rendering, your server’s response to the browser is the HTML of your page that is ready to be rendered so the browser can start rendering without having to wait for all the JavaScript to be downloaded and executed. There’s no “white page” while the browser downloads and executes the JavaScript and other assets needed to render the page, which is what might happen in an entirely client-rendered React site.

And Next js is a  perfect solution for creating react app which are rich in server side rendring capabilities  .

In this article we will see some great stuff in nextjs

  1. Special Pages
  2. Configuration
  3. Extend Webpack

For this article we will first create a nextjs starter project

npx create-next-app sampleapp

now in the pages directory you will have index.js file which will serve as home route for your application and if you want more routes you can just create files and use them as route

  1. pages/index.js  -—> localhost:3000
  2. pages/about.js  -—> localhost:3000/about

Special Pages

The first one is pages/_document.js, which allows us to define the surroundings of the page, such as the Head section. This could be useful to change the page title, add meta information or styles, and so on

// pages/_document.js
import Document, {Head, Main, NextScript} from 'next/document';

export default class MyDocument extends Document {
    render() {
        return (
            <html>
            <Head>
                <title>Smart Next Js</title>
                // Enter Link Tags and scripts tags
            </Head>
            <body>
            <Main/>
            <NextScript/>
            </body>
            </html>
        )
    }
}

we've configured the very basic surroundings of the actual markup that will be injected in the page straight in the body tag; also, we've added a title to the custom Head component.

The next special Page is pages/_app.js, which allows us to wrap all pages (including the error) in a special wrapper

// pages/_app.js
import App, {Container} from 'next/app';
import React from 'react';

export default class MyApp extends App {

  static async getInitialProps ({ Component, router, ctx }) {
    let pageProps = {};
    if (Component.getInitialProps) pageProps = await Component.getInitialProps(ctx);
    return {pageProps};
  }

  state = {someState: ''};

  render () {
    const {Component, pageProps} = this.props
    return (<Container>
      <Component {...pageProps} someState={this.state.someState}/>
    </Container>);
  }

}

The next one is the default 404 or 500 error handler, pages/_error.js

// pages/_error.js
import React from 'react'

export default class Error extends React.Component {
  static getInitialProps({ res, err }) {
    const statusCode = res ? res.statusCode : err ? err.statusCode : null;
    return { statusCode }
  }

  render() {
    return (
      <p>
        {this.props.statusCode
          ? `An error ${this.props.statusCode} occurred on server`
          : 'An error occurred on client'}
      </p>
    )
  }
}

Configuration (use scss  in next js)

Lets add the scss support in our nextjs app

lets create a scss file for style in src/index.scss

body
  font-family: Arial, sans-serif
  font-size: 12px

Lets import this file in pages/_app.js (assuming this is a global stylesheet file if not you can import it in the specific pages also )

and if you run

npm run dev

you will get en error

to resolve it we will first need some npm pacakages

npm install next node-sass @zeit/next-sass --save-dev

next create a file named next.config.js in the route of your app

// next.config.js
const withSass = require('@zeit/next-sass')
module.exports = withSass()

and with this changes you should be able to run your application with scss support

Another useful thing is the configuration of the build/dev phases via custom config.

To do that, you can use the following template:

// next.config.js
const withSass = require('@zeit/next-sass');

const {PHASE_DEVELOPMENT_SERVER} = require('next/constants');

module.exports = (phase, {defaultConfig}) => {

    if(phase === PHASE_DEVELOPMENT_SERVER) {
        return withSass(defaultConfig);
    }

    return withSass(Object.assign({}, defaultConfig, {
        distDir: 'build-new'
    }));

};

Here, we have set the destination directory to build-new. The function receives phase and the defaultConfig as arguments, and you can use phase to determine what has to be modified in defaultConfig, based on your preferences.

Here, config also allows us to expose variables to your pages at runtime:

// next.config.js
const withSass = require("@zeit/next-sass");

const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");

module.exports = (phase, { defaultConfig: defaultConfig }) => {
  if (phase === PHASE_DEVELOPMENT_SERVER) {
    return withSass(defaultConfig);
  }

  return withSass(
    Object.assign({}, defaultConfig, {
      distDir: "build-custom",
    })
  );
};
module.exports = {
  serverRuntimeConfig: {
    secretKey: "secret", 
  },
  publicRuntimeConfig: {
    publicKey: "public", 
  },
};

Extend Webpack (use typescript in next js)

Without next js Plugin

Webpack is the bundler used to produce the Next.js dev server and builds. It can be configured to bundle more things than by default. As an example, let's add TypeScript.

Lets start by creating tsconfig file in the root

tsconfig.json:

{
  "compileOnSave": false,
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "baseUrl": ".",
    "jsx": "preserve",
    "lib": [
      "dom",
      "es2015",
      "es2016"
    ],
    "module": "esnext",
    "moduleResolution": "node",
    "sourceMap": true,
    "skipLibCheck": true,
    "target": "esnext",
    "typeRoots": [
      "./node_modules/@types"
    ]
  }
}

Next lets add some dependencies for type script

npm install ts-loader typescript @types/react 
@types/next @types/node --save-dev

make change in the next.config.js

// next.config.js
const withSass = require("@zeit/next-sass");

const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");

module.exports = (phase, { defaultConfig: defaultConfig }) => {
  if (phase === PHASE_DEVELOPMENT_SERVER) {
    return withSass(defaultConfig);
  }

  return withSass(
    Object.assign({}, defaultConfig, {
      distDir: "build-custom",
    })
  );
};

module.exports = {
  webpack(config, { dir, defaultLoaders }) {
    config.module.rules.push({
      // add a custom loader rule
      test: /\.+(ts|tsx)$/, // apply this rule only to TS[X] files
      use: [
        defaultLoaders.babel, // we use default babel on top of TS
        {
          loader: "ts-loader",
          options: { transpileOnly: true },
        },
      ],
      include: [dir],
      exclude: /node_modules/, // exclude everything from node_modules for performance
    });
    config.resolve.extensions.push(".ts", ".tsx"); // register require resolve extensions
    return config;
  },
};

module.exports = {
  serverRuntimeConfig: {
    serverOnly: "secret", 
  },
  publicRuntimeConfig: {
    serverAndClient: "public",
  },
};

thats it just change index.js to index.tsx and everything should be up and running with typescript now

With Next js Plugin

now as typescript is so popular next already has a plugin for it just install this dependencies

npm install @zeit/next-typescript @types/react @types/next
@types/node --save-dev

add in  next.config.js

// for typescript 
const withTypescript = require('@zeit/next-typescript');
module.exports = withTypescript({});

The final next.config.js will look like this

// next.config.js
const withSass = require("@zeit/next-sass");

const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");

// for typescript 
const withTypescript = require('@zeit/next-typescript');
module.exports = withTypescript({});

module.exports = (phase, { defaultConfig: defaultConfig }) => {
  if (phase === PHASE_DEVELOPMENT_SERVER) {
    return withSass(defaultConfig);
  }

  return withSass(
    Object.assign({}, defaultConfig, {
      distDir: "build-custom",
    })
  );
};


module.exports = {
  serverRuntimeConfig: {
    serverOnly: "secret", 
  },
  publicRuntimeConfig: {
    serverAndClient: "public", 
  },
};

if this is helpfull do share it with the community it motivates to write more

Thanks