Migrating from CRA (create-react-app) to Next.js
Tags: react, nextjs
Published: 2021-01-07 22:59:31

---
title: Migrating from CRA (create-react-app) to Next.js
published: true
date: 2021-01-07 00:00:00 UTC
tags: ['react', 'nextjs']
canonical_url: https://sevic.dev/cra-to-nextjs/
---

I have recently migrated the React app bootstrapped with `create-react-app` to Next.js. The main reason was to improve SEO by making the app more indexable with Next.js, which enables server-side rendering.

This blog post will cover the necessary steps in the migration process.

### Prerequisites

- `next` package (version 13) should be installed
- `@next/eslint-plugin-next` package should be installed as a dev dependency

### Npm scripts

There should be three required scripts in `package.json`.

- `build` builds the app for production usage (the app is built in `.next` directory).
- `dev` runs the development server on the given port.
- `start` runs the production server on the given port.

```json
{
  "scripts": {
    "build": "next build",
    "dev": "next dev -p 1234",
    "start": "next start -p 1234"
  }
}
```

### Environment variables

Environment variables should be prefixed with `NEXT_PUBLIC_` so they can be used in the browser. `dev` and `start` scripts can use variables defined in `.env.local` and `.env.production.local` files, respectively.

```sh
// .env.local
NEXT_PUBLIC_API_URL=http://localhost:8080
```

### Linting

Update the eslint configuration to include the Next.js eslint plugin.

```js
// .eslintrc.js
module.exports = {
  extends: ['plugin:@next/next/recommended'],
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 2022,
    sourceType: 'module'
  }
};
```

### Head tags

Set page-shared `meta` and `link` tags within the root layout component (`app/layout.jsx`).

```jsx
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <link rel="icon" href="/favicon.svg" />
        <link rel="manifest" href="/manifest.json" />
        <meta name="theme-color" content={THEME_COLOR} />
      </head>
      <body>{children}</body>
    </html>
  );
}
```

Export page-specific `meta` tags within `metadata` variables inside server components. Client components have to use `"use-client"` directive.

```js
export const metadata = {
  title: 'nextjs-starter',
  description: 'Minimal Next.js boilerplate',
};
```

### Routing and pages

Pages are associated with a route based on their file name, e.g., `app/home/page.jsx` is mapped to `/home`. Index page component is stored in `app/page.jsx` file.

Implement a custom Not found page in the `app/not-found.jsx` file. Replace the `Link` component from the React router with the `Link` component from the `next/link`.

### Service worker

Register a service worker in the root layout component from `app/layout.jsx` file using the `useEffect` hook. Store it in the `public` folder.

```jsx
'use client';

export default function RootLayout({ children }) {
  useEffect(() => {
    registerServiceWorker();
  }, []);

  // ...
}
```

### State management

This topic is covered in [State management with Next.js and React](https://sevic.dev/notes/state-management-nextjs-react/) post.

### Boilerplate

Here is the [link](https://sevic.dev/nextjs-starter?ref=devto) to the boilerplate I use for the development. It contains the examples mentioned above with more details.