Implementation of next-server and next-app
next-server
next-server is the core server-side module of Next.js, primarily responsible for the following tasks:
- Handling HTTP requests and responses.
- Performing Server-Side Rendering (SSR).
- Serving static assets.
- Processing API routes.
Key Components of next-server:
- Server: Handles HTTP requests.
- Render: Executes server-side rendering.
- Webpack: Manages Webpack configuration and build processes.
- Middleware: Processes middleware logic, such as API routes.
next-app
The next-app module focuses on client-side application logic, including:
- Client-Side Rendering (CSR).
- Client-side route navigation.
- State and lifecycle management.
Key Components of next-app:
- App: The top-level application component.
- Document: Used for rendering the HTML document.
- Router: Manages client-side routing.
- Redux: State management (if used).
Server-Side Rendering (SSR)
// server.js
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});Client-Side Routing
// pages/_app.js
import { useRouter } from 'next/router';
import dynamic from 'next/dynamic';
function MyApp({ Component, pageProps }) {
const router = useRouter();
return <Component {...pageProps} />;
}
export default MyApp;How the Routing System Works
Next.js Routing Types
Next.js has two routing systems:
- Pages Router: The original routing system based on the file system to define page routes.
- App Router: A new routing system introduced in Next.js 13, offering advanced features and improved performance.
Pages Router Mechanics
In the Pages Router, page routes are automatically generated based on the file structure in the /pages directory. For example, a file named pages/about.js corresponds to the /about route.
- Dynamic Routes: If a filename includes square brackets
[ ], it is treated as a dynamic route. For example,pages/post/[id].jscorresponds to the/post/:idpath. - File System Routing: Next.js automatically generates routes based on file names and folder structures.
App Router Mechanics
The App Router, introduced in Next.js 13, provides advanced features like shared layouts and streaming SSR. Its mechanics include:
- File System Routing: Routes are still defined based on the file system but use a new folder structure, such as
/appand/pages. - Shared Layouts: Uses
layout.jsfiles to define reusable layouts, which can be nested. - Streaming SSR: Progressively renders pages to improve First Contentful Paint (FCP).
- Data Fetching: Supports
fetchandusesyntax for data retrieval.
Implementation of Pre-rendering and SSR
Next.js provides two primary methods for handling initial page rendering: Pre-rendering and Server-Side Rendering (SSR). Both aim to enhance application performance and user experience.
Pre-rendering generates static HTML pages at build time, aiding Search Engine Optimization (SEO) and improving initial load speed.
Implementation Mechanics
- Static Generation: Generates static HTML files during the build process, which can be served directly to users after deployment.
- Incremental Static Regeneration (ISR): Allows periodic or manual regeneration of static HTML files post-deployment.
Call Flow of getStaticProps and getServerSideProps
getStaticProps Call Flow
- Build-Time Invocation: During the build process, Next.js iterates through all pages requiring static generation and invokes the
getStaticPropsfunction. - Data Fetching: The
getStaticPropsfunction retrieves data from external sources (e.g., APIs) and returns it as page props. - HTML Generation: Next.js uses the returned data to generate static HTML files, storing them in the
.nextfolder.
// pages/post/[id].js
export default function PostPage({ post }) {
return (
<div>
<h1>Post ID: {post.id}</h1>
<p>Title: {post.title}</p>
<p>Content: {post.content}</p>
</div>
);
}
export async function getStaticProps(context) {
const { params } = context;
const id = params.id;
// Simulate fetching data from a database
const response = await fetch(`https://example.com/api/posts/${id}`);
const post = await response.json();
return {
props: {
post,
},
};
}
export async function getStaticPaths() {
// Simulate fetching all post IDs from a database
const response = await fetch('https://example.com/api/posts');
const posts = await response.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return {
paths,
fallback: false, // Can be set to 'blocking' or 'unstable_blocking' for dynamic routes
};
}Server-Side Rendering (SSR)
SSR involves generating HTML pages on the server in response to each request, ensuring the latest content is delivered.
Implementation Mechanics
- Dynamic Generation: Generates HTML content on the server for each request.
- Data Fetching: Typically fetches data on the server to ensure freshness.
getServerSideProps Call Flow
- Request Arrival: When a user visits an SSR page, the request reaches the server.
- Function Invocation: The server calls the
getServerSidePropsfunction to fetch data. - HTML Generation: Uses the fetched data to generate HTML and sends it to the client.
// pages/post/[id].js
export default function PostPage({ post }) {
return (
<div>
<h1>Post ID: {post.id}</h1>
<p>Title: {post.title}</p>
<p>Content: {post.content}</p>
</div>
);
}
export async function getServerSideProps(context) {
const { params } = context;
const id = params.id;
// Simulate fetching data from a database
const response = await fetch(`https://example.com/api/posts/${id}`);
const post = await response.json();
return {
props: {
post,
},
};
}Route Resolution and Page Rendering
Route Resolution
Next.js supports two routing systems:
- Pages Router: The original routing system, defining page routes based on the file system.
- App Router: A new system introduced in Next.js 13, offering advanced features and improved performance.
Pages Router Mechanics
In the Pages Router, page routes are automatically generated based on the file structure in the /pages directory. For example, a file named pages/about.js corresponds to the /about route.
- Dynamic Routes: If a filename includes square brackets
[ ], it is treated as a dynamic route. For example,pages/post/[id].jscorresponds to the/post/:idpath. - File System Routing: Next.js generates routes based on file names and folder structures.
App Router Mechanics
The App Router, introduced in Next.js 13, provides advanced features like shared layouts and streaming SSR. Its mechanics include:
- File System Routing: Routes are defined based on the file system, using a new folder structure like
/appand/pages. - Shared Layouts: Uses
layout.jsfiles to define reusable, nestable layouts. - Streaming SSR: Progressively renders pages to improve FCP.
- Data Fetching: Supports
fetchandusesyntax for data retrieval.
Page Rendering
Next.js offers multiple methods for handling initial page rendering, including Pre-rendering and SSR.
Pre-rendering
- Static Generation: Generates static HTML files at build time, served directly to users post-deployment.
- Incremental Static Regeneration (ISR): Allows periodic or manual regeneration of static HTML files after deployment.
Server-Side Rendering (SSR)
- Dynamic Generation: Generates HTML content on the server for each request.
- Data Fetching: Fetches data on the server to ensure content freshness.
API Route Handling
Next.js allows defining API routes in the /pages/api directory, primarily used to handle client-side API requests.
API Route Processing Flow
- Request Arrival: The client sends an API request to the server.
- Route Matching: The server matches the request URL to the corresponding API route.
- Request Processing: Invokes the corresponding API function to process the request.
- Response Delivery: Returns the processed result to the client.
// pages/api/posts.js
export default async function handler(req, res) {
if (req.method === 'GET') {
// Fetch data from external API
try {
const response = await fetch('https://example.com/api/posts');
const result = await response.json();
res.status(200).json(result);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to fetch posts' });
}
}
}



