Server-side rendering, also known as SSR, has made such a great impact on the frontend developer community, React announced plans to officially introduce Server Components into the library. You may be wondering what the fuss is all about and why one may want to opt for SSR over the regular client-side rendering that React primarily uses.
SSR has several benefits:
- Better results from SEO (search engine optimization) because search engines are more easily able to crawl SSR rendered sites for keywords and display on the SERPs (search engine results pages) for related content
- Advantages from SMO (social media optimization) that arise from displaying a preview when shared on social media platforms
- Faster loading than client side-rendered applications, making SSR sites more responsive and providing a better user experience
These advantages have led to the rise of the Jamstack architecture, which aims to deliver faster and more consistent web experiences by making use of pre-rendering where assets are compiled on the server during building.
Next.js is one of the most beloved SSR packages in the React community and allows developers to take advantage of the benefits of SSR when building their websites with React.
Next.js provides a zero-configuration setup process similar to what Create React App does through a package called Create Next App. Today, we will look at how you can make use of Next.js on a pre-existing React application. This will allow you to add SSR to an existing project.
Migration process
To show you how this migration is done, we will migrate this project from a previous tutorial, a demo of React components for TypeScript codebases, to use Next.js.
The first step will be to clone the repo, which you can do with either SSH, HTTPS, or the new GitHub CLI:
//SSH git clone [email protected]:austinroy/react-ts-component-demo.git //HTTPS git clone https://github.com/austinroy/react-ts-component-demo.git //GitHub CLI gh repo clone austinroy/react-ts-component-demo
Install the dependencies with the yarn
command and run the application with yarn start
. You should see some basic Star Wars information on your browser that is similar to this sandbox.
Updating scripts and dependencies
This application was set up using Create React App, which uses react-scripts
as its script runner. You will need to replace this with next
.
Uninstall react-scripts
from the project and add next
:
yarn remove react-scripts yarn add next
We used React Router for our page navigation, but Next.js uses a different method of routing, which we will also cover. You will need to also uninstall react-router-dom
:
yarn remove react-router-dom
Our next step is to update any scripts that used react-scripts
to use next
in our scripts section of the package.json
file:
... "scripts": { "dev": "next dev", "build": "next build", "start": "next start" }, ...
next dev
runs a development server on localhost:3000
, and next build
compiles a production ready version of the application, while next start
runs the production version of the application.
Lastly, add .next
to .gitignore
.
Routes and linking
As we mentioned above, Next.js has a totally different method of handling routing and page linking from React Router and react-router-dom
. It has a file system-based router built on the concept of pages, where a page is a React component exported from a .js
, .jsx
, .ts
, or .tsx
file in the pages
directory.
To implement, we will need to create a pages
directory and convert all Route
components in our app to files inside pages
.
mkdir pages && touch pages/index.tsx pages/WithoutTS.jsx
Now let’s create our homepage. Add the following code to your pages/index.tsx
file:
import { DisplayWithTS } from '../src/pages/WithTS' const TSComponent = () => { return( <div className="App"> <a href="/">With TS</a> <br/> <a href="/WithoutTS">Without TS</a> <br/> <br/> <DisplayWithTS /> </div> ) } export default TSComponent
To demo the JavaScript component, we will build the WithoutTS page. Add the following code to the pages/WithoutTS
file:
import { DisplayWithoutTS } from '../src/pages/WithoutTS' const JSCOmponent = () => { return( <div className="App"> <a href="/">With TS</a> <br/> <a href="/WithoutTS">Without TS</a> <br/> <br/> <DisplayWithoutTS /> </div> ) } export default JSCOmponent
Styling
Similarly to Create React App, next
allows you to import styles into components. In Next.js, however, they need to be handled as CSS Modules.
You can, however, add global stylesheets by creating a custom _app.js
file in the pages
directory:
touch pages/_app.js
Import styles into _app.js
and add the following code:
import '../src/App.css' export default function App({ Component, pageProps }) { return <Component className="App" {...pageProps} /> }
You will need to restart the dev server to load up the changes after creating _app.js
. Do this and check your browser; you will now have completely replicated the previous appearance of the application as seen in the code sandbox. And just like that, your application is now rendered on the server side with Next.js. Pretty nice!
Cleanup
Now you can erase files that were generated by Create React App from the src
directory like App.tsx
, App.test.tsx
, index.ts
, index.css
, and serviceWorker.ts
, because Next.js now handles everything these files were doing.
You can also rearrange your folder structure a little as you like, but keep in mind that Next.js uses a file system-based routing mechanism when doing so.
Other things to look into
Now you are all set to get started migrating your old projects to Next.js. For more complex projects, however, you may need to dig a little deeper.
- Access to
window
,localStorage
,navigator
, and other Web APIs – these are usually available to client-side rendered apps out of the box, but since Next.js uses pre-rendering, you will need to access them only on the client-side of your SSR app. One way to do this is with theuseEffect
Hook - Image optimization – while our demo application has no images in it, most web applications will make use of image assets somewhere within them. Next.js provides a custom
Image
Component.next/image
is an extension of the HTML<img>
element, evolved for the modern web. It provides build time optimizations for resizing, optimizing, and serving images in modern formats like WebP when the browser supports it - Environment variables –
.env
variables or secrets are also supported in Next.js just like with Create React App. However, you will need to change theREACT_APP_
prefix toNEXT_PUBLIC_
to make them available at build time next/head
for SEO – Next.js provides a built-in component to append tags to your application’s pagehead
undernext/head
.
Overall, Next.js is one of the best SSR options currently available. Using server-side rendering in your applications has benefits for both user experience, like faster loading, and for exposure by increasing compatibility with SEO and SMO.
Adding Next.js into your already existing React application is a fairly straightforward process that offers a nice glimpse into what the future of frontend web development may look like, leaving many developers excited for what the upcoming React Server Components will hold.
Module not found: Can’t resolve ‘../src/pages/WithTS’
I see no mention of WithTS page, am very confused.