John Au-Yeung I'm a web developer interested in JavaScript stuff.

Comparing Next.js and After.js for SSR React apps

5 min read 1503

comparing next.js after.js server side rendering feature image

Editor’s Note: This post was updated on 1 December 2021 with new code blocks and relevant information.

Next.js and After.js are both frameworks that let us build server-side-rendered React apps without the hassle of setting up SSR from scratch from a create-react-app project. In this article, we’ll compare Next.js and After.js and explore their differences.

Next.js vs. After.js

The major difference between Next.js and After.js is in the routing mechanism.

With Next.js, we don’t specify the routes directly; instead, we let Next.js deal with the routing automatically. It maps URLs to our components by checking the project’s file structure and mapping URLs directly to components with that.

With After.js, we need to specify the routes explicitly. After.js uses React Router to do the routing.

Most of the other features like data fetching and how pages are created are pretty much the same between the two. The way projects are created is done pretty much the same way with their own CLI programs, too.

The easiest way to create a Next.js project is to use create-next-app. To start, run:

npx [email protected]
# or
yarn create next-app
Note: For a Typescript project, add a ​​--typescript flag to this command.

To create an After.js project, we run:

yarn global add create-after-app
// or
npm install -g create-after-app
create-after-app myapp

Note: At the time of writing, After.js throws an error with the latest version of React Router (see the GitHub issue here). A quick fix is to delete our node_modules folder and update package.json, like this:

"dependencies": {
    ...
    "react-router-dom": "^5.3.0"
  }

Once this is done, we can re-install the packages with yarn install or npm install.

Creating pages in Next.js and After.js

Both Next.js and After.js let us create pages by adding React components. To illustrate, we’ll create an app using the News API with Next.js and After.js. All we have to do is create components, and then it’ll display in our app.

For the sake of fetching the data from the News API, we will be using the isomorphic-unfetch package. We can get it by running this command inside our newly created project:

npm i isomorphic-unfetch
// or
yarn add isomorphic-unfetch

We will also need an API key from the News API, which we can create for free.

In Next.js, if we create the page in the pages folder, we can navigate to it via the URL with the same name.

For instance, in Next.js, we can create index.js in the pages folder, as follows:

import NavBar from '../components/navbar'
import fetch from 'isomorphic-unfetch';
import HeadTag from '../components/head-tag';

export async function getStaticProps() {
  const res = await fetch(`https://newsapi.org/v2/top-headlines/?language=en&apiKey=${process.env.NEWS_API_KEY}`)
  const data = await res.json()
  return {
    props: {
      data,
    },
  }
}

const Home = ({ data }) => (
  <div>
    <HeadTag />
    <NavBar />
    {(data.articles) && data.articles.map(a => (
      <div key={a.title}>
        <h1>{a.title}</h1>
        <p>{a.description}</p>
        <p>{a.content}</p>
      </div>
    ))}
  </div>
)

export default Home

The getStaticProps function will let us fetch data, and then we can get it from the props with the same name in our component.

We can create an about page in about.js, as follows:

import NavBar from '../components/navbar'
import HeadTag from '../components/head-tag'

const Home = () => (
  <div>
    <HeadTag />
    <NavBar />
    <p>This is a news app.</p>
  </div>
)

export default Home

Now we can navigate directly to them by going to / and /about, respectively.

After creating the components folder in our root project, we can create components that we can reference on the page by creating the following files:

//head-tag.js

import Head from 'next/head'

const HeadTag = () => (
  <Head>
    <title>News App</title>
  </Head>
)

export default HeadTag
//navbar.js

import Link from 'next/link'

const NavBar = () => (
  <nav>
    <Link href="/">
      <a>Home</a>
    </Link>

    <Link href="/about">
      <a>About</a>
    </Link>
  </nav>
)

export default NavBar

In our After.js app, we created the following components in the src folder:

//Home.js

import React, { Component } from 'react';
import NavBar from './NavBar';
import fetch from 'isomorphic-unfetch';

class Home extends Component {
  static async getInitialProps() {
    const res = await fetch(`https://newsapi.org/v2/top-headlines/?language=en&apiKey=${process.env.RAZZLE_APIKEY}`)
    const data = await res.json();
    return { data };
  }

  render() {
    const { data } = this.props;
    return (
      <div>
        <NavBar />
        {data.articles.map(a => (
          <div key={a.title}>
            <h1>{a.title}</h1>
            <p>{a.description}</p>
            <p>{a.content}</p>
          </div>
        ))}
      </div>
    );
  }
}

export default Home;

We get the data in the initialProps static method, and then we can access it via the props.

//About.js

import React, { Component } from 'react';
import NavBar from './NavBar';

class About extends Component {
  render() {
    return (
      <div>
        <NavBar />
        <p>This is a new app</p>
      </div>
    );
  }
}

export default About;

The components that we reference in the pages can be created in the same folder:

// NavBar.js
import React from 'react';
import { Link } from 'react-router-dom';

class NavBar extends React.Component {

  render() {
    return (
      <div>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
      </div>
    );
  }
}

export default NavBar;

As we can see, these are all just standard components. The difference is that we used the Link component from React Router for page navigation links in After.js, and in the Next.js project, we add page navigation with Next.js’ own Link component.



All that being said, the experience for creating pages is pretty much the same in each framework.

Routing in Next.js vs After.js

Routing is where Next.js and After.js are quite different.

Next.js’ routing works out of the box without much hassle. Once we create the pages, we can navigate to them directly or with links rendered by the Link component.

On the other hand, After.js is a lot trickier. If we have a page component that has the getInitialProps method to fetch data, then we can’t add it to the routes file as an async component.

In our routes.js file, which is in the src folder of our After.js project, we have:

import React from 'react';

import { asyncComponent } from '@jaredpalmer/after';
import Home from './Home';

export default [
  {
    path: '/',
    exact: true,
    component: Home,
  },
  {
    path: '/about',
    exact: true,
    component: asyncComponent({
      loader: () => import('./About'), // required
      Placeholder: () => <div>...LOADING...</div>, // this is optional, just returns null by default
    }),
  },
];

About.js doesn’t fetch data before it renders, so we can include it as an async route. However, the Home component can’t be included as an async route because we have the getInitialProps async method to get data.

Routing is simply easier to deal with in a Next.js project. Routing is more configurable with After.js, but we’ve got to configure it ourselves.

Data fetching in Next.js and After.js

Data fetching in both Next.js and After.js is done when the component is first rendered. As we can see from the previous section, index.js in our Next.js project fetches data in the async getStaticProps function.

In the After.js project, we use the getInitialProps static method of the component class to fetch data before rendering the page.

In both components, the fetched data is available as props within the component.

In Next.js, built-in support has been added for environment variables. All we need is to create a .env.local file in our root project and add:

NEWS_API_KEY=

Once saved, the file will automatically be loaded and the variables used in our application.

And, in the After.js project, environment variables are stored in the .env file, and the keys for environment variables that we can use inside the project must be prefixed with RAZZLE_.

For example, we can write it like this:

RAZZLE_APIKEY=your_api_key

In both frameworks, environment variables are available as a property of the process.env object.

Conclusion

Both Next.js and After.js can be used to build server-side rendered projects. They’re useful for building server-side rendered apps without much effort.

The main difference between Next.js and After.js is the routing. Next.js maps URLs to components by their name and whether the component files are in the pages folder. In contrast, After.js uses React Router for routing, and we’ve got to configure it ourselves.

Get setup with LogRocket's modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    LogRocket.init('app/id');
    Add to your HTML:

    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin
Get started now
John Au-Yeung I'm a web developer interested in JavaScript stuff.

One Reply to “Comparing Next.js and After.js for SSR React apps”

  1. The elephant in the room with Next.js is lack of nested routing[0]. In any moderately complex site, you don’t want to re-render all your components (header/footer) on a page transition. Which also requires you to include your React components on every route path (page.tsx). I was excited to migrate from a Vue.js SSR project to next.js/react, but these basic requirements seem to be lacking. After.js recognises this and uses React Router. But After.js does not have the momentum Next.js has.

    Another issue with Next.js that I think stems from the lack of nested routing is the fact that routes with a getServerSideProps() are called even on client side page transitions[1]. This means that if you fetch data for the entire page, eg user, menu and footer data in getServerSideProps(), this will be fetched again and again on each and every page navigation. There are hacks for these issues, but After.js seems to not have these in the first place.

    [0] https://github.com/vercel/next.js/issues/8193
    [1] [https://github.com/vercel/next.js/issues/11897]

Leave a Reply