How to implement server-side rendering with Next.js
Create a Next.js project, configure the build toolchain, and deploy a React application with server-side rendering on Ubuntu 24.04 using Nginx and Node.js 20.x.
You will create a Next.js application configured for server-side rendering and deploy it behind an Nginx reverse proxy. These steps target Ubuntu 24.04 LTS with Node.js 20.x and Nginx 1.24.x installed.
Prerequisites
- Ubuntu 24.04 LTS server with root or sudo privileges.
- Node.js 20.x and npm installed via NodeSource repository.
- Nginx 1.24.x installed and running.
- A domain name pointing to the server's public IP.
Step 1: Create a Next.js project
Use the Next.js CLI to scaffold a new application with the App Router and server-side rendering enabled by default. Run the create-next-app command with the --yes flag to accept defaults without prompts.
sudo npm create next-app@latest my-ssr-app -- --typescript --eslint --tailwind --src-dir --app --import-alias "@/*" --yes
You will see a directory named my-ssr-app created in your current folder.
Creating a new Next.js app in /home/ubuntu/my-ssr-app
- TypeScript
- ESLint
- Tailwind CSS
- src directory
- App Router
Step 2: Install dependencies
Move into the project directory and install the required packages. Next.js includes the necessary dependencies for server-side rendering out of the box, but you may need to add specific packages if you use custom fonts or icons.
cd my-ssr-app
npm install
Step 3: Configure the environment variables
Create a .env file in the project root to define environment variables for the API routes. This file is not committed to version control by default.
echo "NEXT_PUBLIC_API_URL=http://localhost:3000/api" > .env
Step 4: Create an API route
Build a simple API endpoint to demonstrate data fetching on the server. Create a directory named app/api inside the project root.
mkdir -p app/api/hello
Create a file named [route].ts inside that directory.
touch app/api/hello/[route].ts
Add the following code to the file to return a JSON response.
export async function GET() {
return Response.json({ message: "Hello from Next.js SSR" });
}
Step 5: Create a page component
Create a page that fetches data from the API route you just built. This demonstrates server-side rendering in action.
mkdir -p app/page
Create a file named [route].tsx inside that directory.
touch app/page/[route].tsx
Add the following code to the file to fetch data and render it.
import { Suspense } from "react";
export default async function Page() {
const res = await fetch("http://localhost:3000/api/hello");
const data = await res.json();
return (
Server-Side Rendering Demo
{data.message}
);
}
Step 6: Build the application
Run the production build command to compile the application for deployment. This step generates the optimized static files required for server-side rendering.
npx next build
You will see a summary of the build output including the size of the generated files.
Attention: Next.js now collects completely anonymous telemetry regarding usage.
It does not collect any information about your local network or other devices on your local network.
It does not transmit any data to third parties.
Thank you for using Next.js!
Attention:
The output directory is .next.
...
Successfully generated pages and routes (188 ms)
Step 7: Start the development server
Run the development server to test the application locally before deploying it. This command starts the Next.js development server on port 3000.
npx next dev
Open your browser and navigate to http://localhost:3000 to see the rendered page.
Verify the installation
Visit the application URL in your browser to confirm that the server-side rendering is working correctly. You should see the message Hello from Next.js SSR displayed on the page.
curl http://localhost:3000
You will see the following output:
Server-Side Rendering DemoHello from Next.js SSR
Troubleshooting
If you encounter an error about ENOENT: no such file or directory when running the build command, ensure that the Node.js version is compatible with the Next.js version you installed. Next.js 14.x requires Node.js 18.17 or higher. Check your Node.js version with node -v and upgrade if necessary.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
If the application fails to start, check the logs for errors related to the database or API routes. Ensure that the .env file is correctly configured with the necessary environment variables. If the application is deployed behind Nginx, ensure that the Nginx configuration file includes the correct proxy_pass directive pointing to the Next.js development server or the Node.js process.
sudo nano /etc/nginx/sites-available/nextjs
Add the following configuration to the Nginx file:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Reload Nginx to apply the changes:
sudo nginx -t
sudo systemctl reload nginx
If you encounter issues with the build process, try clearing the .next directory and rebuilding the application.
rm -rf .next
npx next build
Ensure that the firewall allows traffic on port 3000 for the development server or port 80 for the Nginx reverse proxy.
sudo ufw allow 3000
sudo ufw allow 80
Restart the Node.js process or the development server if it stops responding unexpectedly.