Lesson 21-Next.js Source Code Architecture

Next.js Core Module Source Code

File System Routing Implementation

Pages Directory Parsing Source Code Flow:

// packages/next/server/app-dir/module.ts
export function createPagesMapping(pagesDir: string) {
  const pages: Record<string, string> = {};

  // Recursively traverse pages directory
  const files = recursiveReadDirSync(pagesDir);
  files.forEach((file) => {
    // Convert file path to route path
    const routePath = fileToRoutePath(file, pagesDir);
    pages[routePath] = file;
  });

  return pages;
}

// Example: Convert file path to route path
function fileToRoutePath(file: string, pagesDir: string): string {
  const relativePath = path.relative(pagesDir, file);
  return relativePath
    .replace(/\.tsx?$/, '') // Remove extension
    .replace(/\/index$/, '') // Handle index file
    .replace(/\//g, '/');   // Convert to route format
}

Dynamic Routing Implementation:

// packages/next/server/app-dir/dynamic.ts
export function parseDynamicRoute(route: string): DynamicRouteInfo {
  const segments = route.split('/');
  const params: Record<string, string> = {};

  segments.forEach((segment) => {
    if (segment.startsWith('[') && segment.endsWith(']')) {
      const paramName = segment.slice(1, -1);
      params[paramName] = 'string'; // Simplified example, supports multiple types in practice
    }
  });

  return {
    route,
    params,
    isDynamic: Object.keys(params).length > 0
  };
}

Data Fetching Strategies Source Code

getServerSideProps Implementation:

// packages/next/server/app-render/ssr.ts
export async function renderSSR(
  req: NextRequest,
  res: NextResponse,
  pagePath: string,
  getServerSideProps?: GetServerSideProps
) {
  // 1. Execute getServerSideProps function
  let props: Record<string, any> = {};
  if (getServerSideProps) {
    const context = createServerSideContext(req, res);
    props = await getServerSideProps(context);
  }

  // 2. Render React component
  const html = await renderReactComponent(pagePath, props);

  // 3. Return response
  return new NextResponse(html, {
    headers: { 'Content-Type': 'text/html' }
  });
}

getStaticProps Implementation:

// packages/next/server/app-render/ssg.ts
export async function renderSSG(
  pagePath: string,
  getStaticProps?: GetStaticProps
) {
  // 1. Check cache
  const cacheKey = getCacheKey(pagePath);
  const cached = await getStaticCache(cacheKey);
  if (cached) return cached;

  // 2. Execute getStaticProps
  let props: Record<string, any> = {};
  if (getStaticProps) {
    const context = createStaticContext();
    props = await getStaticProps(context);
  }

  // 3. Render React component
  const html = await renderReactComponent(pagePath, props);

  // 4. Cache result
  await setStaticCache(cacheKey, html);

  return html;
}

API Routes Source Code Implementation

API Route Handling Process:

// packages/next/server/api-utils/index.ts
export function createAPIHandler(pagePath: string) {
  return async (req: NextRequest, res: NextResponse) => {
    // 1. Load API module
    const apiModule = await import(pagePath);

    // 2. Get handler function for HTTP method
    const method = req.method?.toLowerCase() || 'get';
    const handler = apiModule[method] || apiModule.default;

    if (!handler) {
      return res.status(405).json({ error: 'Method not allowed' });
    }

    // 3. Execute handler function
    try {
      const result = await handler(req, res);
      if (!res.writableEnded) {
        res.json(result);
      }
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  };
}

Middleware Source Code Implementation

Middleware Execution Process:

// packages/next/server/middleware.ts
export async function runMiddleware(
  req: NextRequest,
  res: NextResponse,
  middlewarePath: string
) {
  // 1. Load middleware module
  const middlewareModule = await import(middlewarePath);
  const middleware = middlewareModule.default;

  // 2. Execute middleware
  const middlewareResult = await middleware(req, res);

  // 3. Handle middleware result
  if (middlewareResult instanceof NextResponse) {
    // Middleware returned a new Response
    return middlewareResult;
  } else if (middlewareResult === undefined) {
    // Middleware did not return anything, continue with subsequent logic
    return undefined;
  } else {
    // Invalid middleware return value
    throw new Error('Invalid middleware return value');
  }
}

Static Resource Management Source Code

Public Directory Handling:

// packages/next/server/static-files.ts
export async function serveStaticFile(
  req: NextRequest,
  publicDir: string
) {
  // 1. Parse request path
  const filePath = path.join(publicDir, req.nextUrl.pathname);

  // 2. Check if file exists
  if (!fs.existsSync(filePath)) {
    return null;
  }

  // 3. Read file content
  const content = fs.readFileSync(filePath);

  // 4. Set correct Content-Type
  const contentType = getContentType(filePath);

  // 5. Return response
  return new NextResponse(content, {
    headers: { 'Content-Type': contentType }
  });
}

next/image Optimization Implementation:

// packages/next/shared/lib/image-utils.ts
export async function optimizeImage(
  src: string,
  width: number,
  height: number,
  quality: number
) {
  // 1. Check if image format is supported
  if (!supportedFormats.includes(getImageFormat(src))) {
    throw new Error('Unsupported image format');
  }

  // 2. Generate cache key
  const cacheKey = generateCacheKey(src, width, height, quality);

  // 3. Check cache
  const cached = await getImageCache(cacheKey);
  if (cached) return cached;

  // 4. Download original image
  const originalImage = await downloadImage(src);

  // 5. Process image using Sharp
  const optimizedImage = await sharp(originalImage)
    .resize(width, height)
    .jpeg({ quality })
    .toBuffer();

  // 6. Cache result
  await setImageCache(cacheKey, optimizedImage);

  return optimizedImage;
}

Rendering and Compilation Source Code

Server-Side Rendering (SSR) Source Code

SSR Core Process:

// packages/next/server/render.ts
export async function renderToHTML(
  req: NextRequest,
  res: NextResponse,
  pagePath: string,
  query: Record<string, any>
) {
  // 1. Create React application context
  const appContext = createAppContext(req, res);

  // 2. Load page component
  const pageModule = await import(pagePath);
  const PageComponent = pageModule.default;

  // 3. Execute getServerSideProps (if exists)
  let props: Record<string, any> = {};
  if (PageComponent.getServerSideProps) {
    props = await PageComponent.getServerSideProps(appContext);
  }

  // 4. Render React component to HTML
  const html = await renderToString(
    <AppContext.Provider value={appContext}>
      <PageComponent {...props} />
    </AppContext.Provider>
  );

  // 5. Inject necessary scripts and styles
  const finalHtml = injectScriptsAndStyles(html);

  return finalHtml;
}

Static Site Generation (SSG) Source Code

SSG Build Process:

// packages/next/build/static-generation.ts
export async function buildStaticPages(
  pagesDir: string,
  outDir: string
) {
  // 1. Get all page paths
  const pages = await discoverPages(pagesDir);

  // 2. Generate all static pages in parallel
  await Promise.all(
    pages.map(async (pagePath) => {
      // 1. Execute getStaticProps (if exists)
      const props = await getStaticPropsForPage(pagePath);

      // 2. Render React component to HTML
      const html = await renderToString(
        <PageComponent {...props} />
      );

      // 3. Write to file system
      const outputPath = path.join(outDir, pagePathToFilePath(pagePath));
      fs.writeFileSync(outputPath, injectScriptsAndStyles(html));
    })
  );
}

Incremental Static Regeneration (ISR) Source Code

ISR Implementation Mechanism:

// packages/next/server/revalidate.ts
export async function handleRevalidation(
  req: NextRequest,
  pagePath: string,
  revalidateConfig: RevalidateConfig
) {
  // 1. Check if revalidation is needed
  const lastRevalidated = await getLastRevalidatedTime(pagePath);
  const now = Date.now();

  if (now - lastRevalidated < revalidateConfig.interval * 1000) {
    // Not time for revalidation, return cached content
    return getCachedHTML(pagePath);
  }

  // 2. Perform revalidation
  const props = await getStaticPropsForPage(pagePath);
  const html = await renderToString(
    <PageComponent {...props} />
  );

  // 3. Update cache
  await updateCache(pagePath, html);
  await setLastRevalidatedTime(pagePath, now);

  return html;
}

Compiler Workflow Source Code

Compilation Process from React Component to HTML:

// packages/next/compiler/index.ts
export async function compilePage(pagePath: string) {
  // 1. Parse React component
  const component = await parseReactComponent(pagePath);

  // 2. Transform to Next.js-specific format
  const transformed = transformComponent(component);

  // 3. Generate static HTML
  const html = await generateStaticHTML(transformed);

  // 4. Extract CSS and JavaScript
  const { styles, scripts } = extractAssets(transformed);

  // 5. Generate final output
  return {
    html,
    styles,
    scripts
  };
}

Performance Optimization Source Code

Code Splitting Implementation:

// packages/next/compiler/code-splitting.ts
export function applyCodeSplitting(component: ReactComponent) {
  // 1. Analyze component dependencies
  const dependencies = analyzeDependencies(component);

  // 2. Group dependencies into chunks
  const chunks = groupDependenciesIntoChunks(dependencies);

  // 3. Generate dynamic import code
  const transformed = transformToDynamicImports(component, chunks);

  return transformed;
}

Lazy Loading Implementation:

// packages/next/compiler/lazy-loading.ts
export function applyLazyLoading(component: ReactComponent) {
  // 1. Identify parts suitable for lazy loading
  const lazyParts = identifyLazyParts(component);

  // 2. Wrap with React.lazy calls
  const transformed = wrapWithReactLazy(component, lazyParts);

  // 3. Add Suspense boundary
  const finalComponent = addSuspenseBoundary(transformed);

  return finalComponent;
}

Middleware and Edge Functions Source Code

Middleware Execution Flow Source Code

Middleware Execution Order:

// packages/next/server/middleware-runner.ts
export async function runMiddlewareChain(
  req: NextRequest,
  res: NextResponse,
  middlewareChain: Middleware[]
) {
  let currentRes = res;

  // Execute middleware in sequence
  for (const middleware of middlewareChain) {
    // Execute current middleware
    const result = await middleware(req, currentRes);

    // If middleware returns a new Response, stop executing subsequent middleware
    if (result instanceof NextResponse) {
      currentRes = result;
      break;
    }

    // Update current Response
    currentRes = result || currentRes;
  }

  return currentRes;
}

Edge Functions Source Code Implementation

Edge Function Execution Environment:

// packages/next/server/edge-runtime.ts
export function createEdgeRuntime() {
  // 1. Initialize lightweight runtime environment
  const runtime = new EdgeRuntime();

  // 2. Inject necessary APIs
  runtime.injectAPIs({
    fetch: globalThis.fetch,
    Request: globalThis.Request,
    Response: globalThis.Response,
    // ...other necessary APIs
  });

  return runtime;
}

// Handle edge function request
export async function handleEdgeRequest(
  req: NextRequest,
  edgeFunctionPath: string
) {
  // 1. Load edge function
  const edgeFunction = await import(edgeFunctionPath);

  // 2. Execute edge function
  const result = await edgeFunction.default(req);

  // 3. Return response
  return result instanceof Response ? result : new Response(result);
}

Performance Optimization Source Code

Middleware Cache Strategy:

// packages/next/server/middleware-cache.ts
export class MiddlewareCache {
  private cache: Map<string, CachedResponse> = new Map();

  async getOrCreate(
    key: string,
    factory: () => Promise<NextResponse>
  ): Promise<NextResponse> {
    // 1. Check cache
    if (this.cache.has(key)) {
      const cached = this.cache.get(key)!;
      if (!isCachedResponseInvalid(cached)) {
        return cached.response;
      }
    }

    // 2. Execute factory function
    const response = await factory();

    // 3. Cache result
    this.cache.set(key, {
      response,
      timestamp: Date.now()
    });

    return response;
  }
}

Security Strategy Source Code

Middleware Security Validation:

// packages/next/server/middleware-security.ts
export function applySecurityMiddleware(req: NextRequest, res: NextResponse) {
  // 1. CSRF protection
  if (isUnsafeMethod(req.method)) {
    verifyCSRFToken(req);
  }

  // 2. CORS validation
  if (req.method === 'OPTIONS') {
    handlePreflightRequest(req, res);
    return res;
  }

  // 3. Content Security Policy
  res.headers.set('Content-Security-Policy', getCSPHeader());

  // 4. Other security headers
  res.headers.set('X-Frame-Options', 'DENY');
  res.headers.set('X-Content-Type-Options', 'nosniff');

  return res;
}

Debugging and Testing Source Code

Middleware Testing Tools:

// packages/next/server/middleware-test-utils.ts
export function createTestMiddlewareContext() {
  // 1. Create mock request
  const mockReq = new NextRequest('https://example.com/test');

  // 2. Create mock response
  const mockRes = new NextResponse();

  // 3. Create mock Next.js environment
  const mockEnv = {
    // ...mock environment variables and methods
  };

  return { mockReq, mockRes, mockEnv };
}

// Edge function testing tools
export function createTestEdgeRuntime() {
  // 1. Create lightweight runtime
  const runtime = createEdgeRuntime();

  // 2. Inject testing utilities
  runtime.injectTestUtils({
    // ...test utility methods
  });

  return runtime;
}

Summary

The source code architecture of Next.js 14 showcases the design essence of a modern web framework:

  1. File System Routing: Maps the file system to the routing system through a convention-over-configuration approach.
  2. Hybrid Rendering Modes: Supports SSR, SSG, and ISR to meet various use case requirements.
  3. Middleware System: Provides a flexible request handling pipeline for A/B testing, redirects, and more.
  4. Edge Computing: Achieves lower latency and higher performance through edge functions.
  5. Performance Optimization: Enhances application performance through code splitting and static generation.

These source code implementations demonstrate how Next.js balances developer experience with the performance and scalability required for enterprise-grade applications.

Share your love