Build Server-side rendered React apps with NextJS
May 11, 2020
Why NextJS?
Most frontend build tools (i.e. create-react-app) are are Client rendered by default, and will not be optimized for Google’s search engine crawlers. This problem has been solved by NextJS and Gatsby, which are currently the most popular build tools for Server rendering in React. Server rendering is useful for sites like stores or blogs to rank better in SEO by sending all metadata with the initial page load.
NextJS Features
NextJS is a flexible build tool for React that specializes in creating Server rendered dynamic applications. Next abstracts away the Webpack config and comes with Hot Reloading for development. Next also uses Automatic Routing by associating page files with routes. Additionally, Next takes care of Code Splitting to reduce initial page load. Pages can also be Prefetched with by adding a prop on the Next Link component.
NextJS Project Setup
To quickly setup a Next project use the command
npx create-next-app next-demo
This will setup a new project folder with the name next-demo
, exactly like create-react-app would. Select the default options for any promts you might get. npx is a command that will search the npm registry for the newest version of create-next-app and use it to build our project. This saves us from having to install next globally, which can also be done if preferred.
Next projects can also be setup manually, though we will run the project initialized above using create-next-app.
cd next-demo
code .
npm run dev
Shortcut: the command
code .
in the terminal will open VS Code in thenext-demo
folder if you have it installed You’ll notice that create-next-app setup the following for us:
- a
pages
folder - a
public
folder - installed dependencies: next, react, and react-dom
- added next scripts:
dev
,build
, andstart
to the package.json file.
Take some time now to look through the index.js
file in the pages
folder. This will be our homepage route and this file provides some examples of various Next features. This boilerplate page will likely change with new versions of Next, but still contains examples of how to handle metadata and setup inline CSS styles (locally or globally).
Pages and Routing
Each .js file in the pages
folder will automatically generate a page at the route it is named, if it is a valid React component. Pages and components do not need to import React from 'react'
at the top as Next already imports this on every component. Create a new component in the pages
folder called about.js
const About = () => (
<div>
<h2>About Page</h2>
</div>
);
export default About;
This page will be available at the /about
route.
Adding dynamic pages
It is also possible to create pages based on the value of the URL parameter. Add a folder in your pages
folder named projects
and in that add a file named [slug].js
. Add the following code to [slug].js
import { useRouter } from "next/router";
const Projects = () => {
const router = useRouter();
const { slug } = router.query;
return <h2>{slug}</h2>;
};
export default Projects;
This will set load a page for us whenever a /projects/your-slug-here
URL is hit. The name of the slug is available on router.query
when using the next/router
package.
Index Page
The index.js
file is full of boilerplate code that we can replace with the following
import Link from "next/link";
function Home() {
return (
<div>
<nav>
<Link href="/">
<a>Home</a>
</Link>
<Link href="/about">
<a>About</a>
</Link>
<Link href="/projects/first-project">
<a>First Project</a>
</Link>
</nav>
<div className="container">
<h1>Create Next App Starter</h1>
</div>
<style jsx global>{`
html,
body {
font-family: -apple-system, Fira Sans, Helvetica Neue, sans-serif;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
nav {
padding: 20px 0;
text-align: center;
position: fixed;
top: 0;
}
a {
margin: 0 10px;
}
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
`}</style>
</div>
);
}
export default Home;
At the top, Next handles links a little differently than other routing methods such as react-router or Gatsby. In Next, The <a></a>
tag is wrapped by <Link></Link>
tags. The main different is that the href
property goes on the Link tag, instead of on the anchor tag.
You’ll notice there are also <style jsx>
tags which contain some css. These tags are specific to the component they are declared in, unless the global
property is added in which case they are global styles.
Now visit the /about
page and you will also realize our navigation is only available on the homepage.
Custom App Page
We can add this navigation to every page by creating a _app.js
file in the pages
folder, which Next will load on every route. Create this file now in the pages
folder and add the following
import Layout from "../components/Layout";
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
Also create a components
folder and and Layout.js
file with the following
import Link from "next/link";
const Layout = ({ children }) => {
return (
<div className="container">
<main>{children}</main>
</div>
);
};
export default Layout;
It also makes sense to switch over the navigation and global css styles code from index.js
to Layout.js
since it will be loaded on every page, let’s do that next.
If you are following along in the browser, we will need to restart our development server to use this component on every page.
Adding Meta Tags
We can add metadata to our pages using the Next Head
component. This component can be used in any page or component, let’s create a Meta.js
component now to add metadata that should show up on every page. (Make sure to import and include this component in the recently created Layout.js
)
import Head from "next/head";
const Meta = () => {
return (
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charSet="utf-8" />
<link rel="shortcut icon" href="/public/favicon.png" />
<title>Next Demo</title>
</Head>
);
};
export default Meta;
Here we added some basic site information, feel free to change the title and add more tags of your own. It also makes sense to make some page-specific meta tags for better SEO. Also replace the about.js
page with the following
import Head from "next/head";
const About = (props) => {
return (
<div>
<Head>
<title>About Page</title>
<meta
name="description"
content="This is the about page for the website"
/>
<meta
name="twitter:description"
content="This is the about page for the website"
/>
<meta
property="og:description"
content="This is the about page for the website"
/>
</Head>
<h2>About Page</h2>
</div>
);
};
export default About;
Here we have another second title, About Page. Since we are lower in the project tree than the Page
component, this title will overwrite our Next Demo title from above. This title tag shows up in the browser tab and is useful to change for specific pages. We also added description meta tags which are specific to this content.
It makes sense to setup a SEO component which receives and includes all of this data in a template, rather than copy it out individually. This is especially true for blog posts or large numbers of pages.
Other Methods for CSS
Next.js comes with all the standard methods for using CSS.
CSS
To use a .css
stylesheet, add a standard import statement to the _app.js
page component from earlier. These styles will get applied to every page, and it is important to only upload .css
files here to avoid naming conflicts.
SCSS
To use a .scss
styledsheet, first install the sass
package with
npm install sass
Add an import for your .scss
file to the _app.js
component like you would importing a CSS file.
Other CSS Methods
Next has a solution for pretty much every CSS method. There is support for CSS Modules, Styled Components, Less, Stylus, and more.
Deployment with Now
There are two, equally simple hosting options for a Next.js project using Now. Both methods require using a Now account which you can sign up for here.
Command Line Deploy
To install Now
globally, enter the following in your terminal
npm i -g now
This will allow you to deploy by using the command
now
when inside the project you wish to deploy. If it is a new project, you will be asked to provide a name and some basic settings. Selecting the default settings for each question will deploy your Next app. You will get a hosted production link such as
https://next-test-app-seven.now.sh
along with some other links to your Now deploy overview and project settings page.
Import Project (Now Dashboard)
In the Now Dashboard, there is an option for Import Project
. This will allow you to choose a Github, Gitlab, or Bitbucket repository to deploy. This service will detect your build configuration and fill out the build command + start scripts automatically.
Simply sit back and way for the server to deploy!
Conclusion
Next and Now is a powerhouse combination for hosting Server rendered front-end applications. Zeit, the team behind both projects, is often innovating and adding new features.