Next.js vs React: Core Concepts Comparison
Introduction
React is a JavaScript library for building user interfaces, while Next.js is a React framework that adds powerful features like server-side rendering, routing, and optimizations on top of React.
1. Project Setup
React
- Requires manual configuration or tools like Create React App
- Need to set up bundler (Webpack, Vite)
- Manual routing setup required
- More configuration needed for production optimization
npx create-react-app my-app
Next.js
- Built-in configuration and optimization
- Zero-config setup out of the box
- File-based routing included
- Production-ready from the start
npx create-next-app my-app
2. Routing
React
- Requires third-party library (React Router)
- Programmatic routing setup
- Manual route configuration
// React with React Router
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
Next.js
- File-based routing system
- Files in
/pagesor/appdirectory automatically become routes - Dynamic routes with bracket notation
- Nested routing supported natively
// Next.js - File structure creates routes
// pages/index.js → /
// pages/about.js → /about
// pages/blog/[id].js → /blog/:id
// pages/index.js
export default function Home() {
return <h1>Home Page</h1>;
}
3. Rendering Methods
React
- Client-Side Rendering (CSR) only by default
- JavaScript executes in the browser
- Initial HTML is minimal
- Can lead to slower initial page loads
- SEO challenges without additional setup
// Standard React component (CSR)
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
}, []);
return <div>{data?.title}</div>;
}
Next.js
Supports multiple rendering strategies:
1. Static Site Generation (SSG)
- Pages generated at build time
- Best performance
- Ideal for content that doesn't change often
// getStaticProps runs at build time
export async function getStaticProps() {
const data = await fetch('https://api.example.com/data');
return { props: { data: await data.json() } };
}
export default function Page({ data }) {
return <div>{data.title}</div>;
}
2. Server-Side Rendering (SSR)
- Pages generated on each request
- Always up-to-date content
- Better SEO
// getServerSideProps runs on every request
export async function getServerSideProps() {
const data = await fetch('https://api.example.com/data');
return { props: { data: await data.json() } };
}
3. Client-Side Rendering (CSR)
- Same as React, available when needed
4. Incremental Static Regeneration (ISR)
- Static pages that update periodically
- Best of both worlds
export async function getStaticProps() {
const data = await fetch('https://api.example.com/data');
return {
props: { data: await data.json() },
revalidate: 60 // Regenerate every 60 seconds
};
}
4. Data Fetching
React
- Manual data fetching with
fetchor libraries - Use
useEffectfor side effects - State management with
useState - No built-in data fetching patterns
function UserProfile() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => {
setUser(data);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return <div>{user.name}</div>;
}
Next.js
- Multiple built-in data fetching methods
- Server-side data fetching capabilities
- Automatic serialization and hydration
// Next.js App Router (modern approach)
async function UserProfile() {
const user = await fetch('/api/user').then(r => r.json());
return <div>{user.name}</div>;
}
// Or with Pages Router
export async function getServerSideProps() {
const user = await fetch('/api/user').then(r => r.json());
return { props: { user } };
}
export default function UserProfile({ user }) {
return <div>{user.name}</div>;
}
5. API Routes
React
- No built-in API layer
- Requires separate backend server
- Need Express, Node.js, or other backend framework
// Separate backend required
// Must set up Express server separately
const express = require('express');
const app = express();
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});
Next.js
- Built-in API routes
- Create APIs in
/pages/apior/app/api - Serverless functions by default
// pages/api/users.js
export default function handler(req, res) {
res.status(200).json({ users: ['Alice', 'Bob'] });
}
// Access at: /api/users
6. Image Optimization
React
- Standard
<img>tag - Manual optimization required
- No automatic responsive images
- Must handle lazy loading manually
// React
function MyImage() {
return <img src="/photo.jpg" alt="Photo" />;
}
Next.js
- Built-in
Imagecomponent - Automatic optimization and resizing
- Lazy loading by default
- WebP format conversion
- Responsive images automatically
// Next.js
import Image from 'next/image';
function MyImage() {
return (
<Image
src="/photo.jpg"
alt="Photo"
width={500}
height={300}
placeholder="blur"
/>
);
}
7. Code Splitting
React
- Manual code splitting with
React.lazy() - Requires configuration
- More manual work for optimization
// React
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
Next.js
- Automatic code splitting
- Each page is automatically split
- Optimized bundle sizes out of the box
- Dynamic imports work seamlessly
// Next.js - automatic per-page code splitting
// Each page only loads its own JavaScript
// Dynamic import when needed
import dynamic from 'next/dynamic';
const DynamicComponent = dynamic(() => import('./Component'), {
loading: () => <p>Loading...</p>
});
8. SEO and Meta Tags
React
- Manual meta tag management
- Requires libraries like React Helmet
- Client-side meta updates
// React with React Helmet
import { Helmet } from 'react-helmet';
function Page() {
return (
<>
<Helmet>
<title>My Page</title>
<meta name="description" content="Page description" />
</Helmet>
<h1>Content</h1>
</>
);
}
Next.js
- Built-in
Headcomponent - Server-rendered meta tags (better SEO)
- Metadata API in App Router
// Next.js Pages Router
import Head from 'next/head';
export default function Page() {
return (
<>
<Head>
<title>My Page</title>
<meta name="description" content="Page description" />
</Head>
<h1>Content</h1>
</>
);
}
// Next.js App Router
export const metadata = {
title: 'My Page',
description: 'Page description'
};
9. Styling Options
React
- CSS Modules (with configuration)
- Styled Components
- CSS-in-JS libraries
- Regular CSS files
- Manual setup for most solutions
Next.js
- CSS Modules built-in
- Sass support out of the box
- CSS-in-JS support
- Tailwind CSS easy integration
- Global styles with
_app.js
// Next.js CSS Modules
import styles from './Button.module.css';
export default function Button() {
return <button className={styles.primary}>Click me</button>;
}
10. Performance Optimization
React
- Manual optimization needed
- Configure bundler for tree shaking
- Manual lazy loading setup
- No automatic prefetching
Next.js
- Automatic optimizations
- Built-in image optimization
- Automatic code splitting
- Link prefetching
- Static optimization when possible
- Incremental Static Regeneration
11. Deployment
React
- Deploy to any static hosting
- Manual build configuration
- Need separate backend for APIs
Next.js
- Optimized for Vercel (one-click deploy)
- Deploy to any Node.js hosting
- Serverless functions included
- Edge runtime support
- Automatic CI/CD pipelines
When to Use Each
Use React When:
- Building a single-page application (SPA)
- You need maximum flexibility
- SEO is not a primary concern
- You have an existing backend
- Building a component library
- You prefer minimal framework overhead
Use Next.js When:
- SEO is critical
- You need server-side rendering
- Building a content-heavy website
- You want full-stack capabilities in one framework
- Performance is a top priority
- You need multiple rendering strategies
- Building an e-commerce site or blog
Key Takeaways
React is a library focused on building user interfaces with a component-based approach. It gives you flexibility but requires more setup and configuration.
Next.js is a full-featured framework built on React that provides:
- Better SEO out of the box
- Multiple rendering strategies
- Built-in routing
- API routes for full-stack development
- Superior performance optimizations
- Production-ready configuration
Next.js extends React's capabilities while maintaining React's core principles, making it ideal for production applications that need SEO, performance, and developer experience.