Lesson 13-Nuxt.js Source Code Architecture

Nuxt.js Core Module Source Code

File System Routing Implementation

Pages Directory Parsing Process:

// packages/nuxt/src/core/runtime/nitro/router.ts
export class NuxtRouter {
  private pagesMap: Record<string, string> = {}

  // Initialize route mapping
  async buildPagesMap(pagesDir: string) {
    // 1. Recursively scan pages directory
    const files = await recursiveReadDir(pagesDir)

    // 2. Convert file paths to route paths
    files.forEach(file => {
      const routePath = this.fileToRoutePath(file, pagesDir)
      this.pagesMap[routePath] = file
    })

    // 3. Process dynamic routes
    this.processDynamicRoutes()
  }

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

  // Dynamic route processing
  processDynamicRoutes() {
    // 1. Identify dynamic parameter patterns
    const dynamicRoutes = Object.keys(this.pagesMap).filter(route => 
      route.includes(':') || route.includes('[')
    )

    // 2. Generate dynamic route regex
    dynamicRoutes.forEach(route => {
      const regex = this.convertToRegex(route)
      this.dynamicRouteMap[regex] = this.pagesMap[route]
    })
  }
}

Data Fetching Strategy Source Code

asyncData Execution Process:

// packages/nuxt/src/core/runtime/composition-api.ts
export function useAsyncData(
  key: string,
  fn: () => Promise<any>,
  options: AsyncDataOptions = {}
) {
  // 1. Create reactive data container
  const data = ref(null)
  const error = ref(null)
  const state = ref('idle') // 'idle' | 'pending' | 'success' | 'error'

  // 2. Execute data fetching
  const execute = async () => {
    state.value = 'pending'
    try {
      // Server-first execution
      if (process.server) {
        data.value = await fn()
      } else {
        // Client-side cache check
        const cached = useNuxtApp().payload.data[key]
        if (cached) {
          data.value = cached
        } else {
          data.value = await fn()
        }
      }
      state.value = 'success'
    } catch (err) {
      error.value = err
      state.value = 'error'
    }
  }

  // 3. Immediate or deferred execution
  if (options.lazy) {
    // Deferred execution
    const promise = execute()
    return { data, error, state, refresh: execute }
  } else {
    // Immediate execution
    execute()
    return { data, error, state, refresh: execute }
  }
}

fetch Implementation Mechanism:

// packages/nuxt/src/core/runtime/fetch.ts
export function useFetch(request: any, options: FetchOptions = {}) {
  // 1. Get request context
  const nuxtApp = useNuxtApp()
  const key = options.key || request

  // 2. Check cache
  if (options.key && nuxtApp.payload.data[key]) {
    return Promise.resolve(nuxtApp.payload.data[key])
  }

  // 3. Execute request
  return nuxtApp.$fetch(request, {
    ...options,
    onRequest({ options }) {
      // Request interception
      if (options.headers) {
        options.headers['X-Nuxt-Fetch'] = 'true'
      }
    },
    onResponse({ response }) {
      // Response handling
      if (key) {
        nuxtApp.payload.data[key] = response._data
      }
    }
  })
}

API Route Source Code Implementation

serverMiddleware Processing Flow:

// packages/nuxt/src/core/server/middleware.ts
export function createServerMiddleware(nuxt: Nuxt) {
  return async (req: IncomingMessage, res: ServerResponse, next: Function) => {
    // 1. Parse request path
    const pathname = url.parse(req.url).pathname

    // 2. Find matching API route
    const matchedMiddleware = nuxt.options.serverMiddleware.find(middleware => {
      if (typeof middleware === 'function') {
        return true // Function middleware matches all paths
      }
      return pathname.startsWith(middleware.path)
    })

    // 3. Execute matched middleware
    if (matchedMiddleware) {
      if (typeof matchedMiddleware === 'function') {
        await matchedMiddleware(req, res, next)
      } else {
        const middlewareModule = await import(matchedMiddleware.handler)
        await middlewareModule.default(req, res, next)
      }
    } else {
      next() // Proceed to next middleware
    }
  }
}

Module System Source Code

Module Loading Process:

// packages/nuxt/src/core/modules/loader.ts
export async function loadModules(nuxt: Nuxt) {
  // 1. Load built-in modules
  await loadBuiltInModules(nuxt)

  // 2. Load project modules
  const modulePaths = await findModulePaths(nuxt.options.rootDir)

  // 3. Load modules sequentially
  for (const modulePath of modulePaths) {
    await loadSingleModule(modulePath, nuxt)
  }

  // 4. Execute module lifecycle
  await runModuleLifecycleHooks('ready', nuxt)
}

// Single module loading implementation
async function loadSingleModule(modulePath: string, nuxt: Nuxt) {
  // 1. Import module
  const module = await import(modulePath)

  // 2. Validate module structure
  if (!module.default || typeof module.default !== 'function') {
    throw new Error(`Invalid module at ${modulePath}`)
  }

  // 3. Call module factory function
  const moduleInstance = await module.default({
    nuxt,
    ...moduleOptions
  })

  // 4. Register module
  nuxt.modules.push(moduleInstance)
}

Static Asset Management

public Directory Processing:

// packages/nuxt/src/core/server/static.ts
export function serveStaticFiles(nuxt: Nuxt) {
  return async (req: IncomingMessage, res: ServerResponse, next: Function) => {
    // 1. Parse request path
    const pathname = url.parse(req.url).pathname

    // 2. Build file path
    const filePath = path.join(nuxt.options.rootDir, 'public', pathname)

    // 3. Check if file exists
    if (fs.existsSync(filePath)) {
      // 4. Set correct Content-Type
      const contentType = getContentType(filePath)
      res.setHeader('Content-Type', contentType)

      // 5. Send file
      fs.createReadStream(filePath).pipe(res)
    } else {
      next() // Proceed to next middleware
    }
  }
}

assets Directory Processing:

// packages/nuxt/src/core/compiler/assets.ts
export function processAssets(nuxt: Nuxt) {
  // 1. Collect all static assets
  const assets = glob.sync('**/*', { cwd: nuxt.options.dir.assets })

  // 2. Process each asset type
  assets.forEach(asset => {
    const fullPath = path.join(nuxt.options.dir.assets, asset)
    const content = fs.readFileSync(fullPath)

    // 3. Process based on file type
    switch (path.extname(asset)) {
      case '.css':
        processCSS(content, asset)
        break
      case '.js':
        processJS(content, asset)
        break
      case '.scss':
      case '.less':
        processPreprocessor(content, asset)
        break
    }
  })
}

Rendering and Compilation Source Code

Server-Side Rendering (SSR) Source Code

SSR Rendering Process:

// packages/nuxt/src/core/render/ssr.ts
export async function renderSSR(nuxt: Nuxt, req: IncomingMessage, res: ServerResponse) {
  // 1. Create render context
  const context = createRenderContext(nuxt, req, res)

  // 2. Execute asyncData and fetch
  await executeAsyncData(context)

  // 3. Render Vue component
  const html = await renderVueComponent(context)

  // 4. Inject client scripts
  const finalHtml = injectClientScripts(html, context)

  // 5. Send response
  res.setHeader('Content-Type', 'text/html')
  res.end(finalHtml)
}

// Vue component rendering implementation
async function renderVueComponent(context: RenderContext) {
  // 1. Create Vue app instance
  const app = createApp(context)

  // 2. Perform server-side rendering
  const { html } = await renderToString(app)

  // 3. Handle hydration data
  const hydrationData = generateHydrationData(context)

  return `
    ${renderHead(context)}
    <div id="app">${html}</div>
    <script>window.__NUXT__=${JSON.stringify(hydrationData)}</script>
  `
}

Static Site Generation (SSG) Source Code

SSG Build Process:

// packages/nuxt/src/core/build/ssg.ts
export async function generateStaticSite(nuxt: Nuxt) {
  // 1. Get all routes
  const routes = await discoverRoutes(nuxt)

  // 2. Generate all pages in parallel
  await Promise.all(
    routes.map(async route => {
      // 1. Create static context
      const context = createStaticContext(nuxt, route)

      // 2. Execute asyncData and fetch
      await executeAsyncData(context)

      // 3. Render Vue component
      const html = await renderVueComponent(context)

      // 4. Write to file system
      const outputPath = path.join(nuxt.options.generate.dir, route + '.html')
      fs.writeFileSync(outputPath, html)
    })
  )
}

Incremental Static Regeneration (ISR) Source Code

ISR Implementation Mechanism:

// packages/nuxt/src/core/render/isr.ts
export class ISRManager {
  private cache: Map<string, { html: string, timestamp: number }> = new Map()

  // Handle ISR request
  async handleRequest(route: string, renderFn: () => Promise<string>) {
    // 1. Check cache
    const cached = this.cache.get(route)
    if (cached && !this.isCacheExpired(cached)) {
      return cached.html
    }

    // 2. Perform re-rendering
    const html = await renderFn()

    // 3. Update cache
    this.cache.set(route, {
      html,
      timestamp: Date.now()
    })

    return html
  }

  // Cache expiration check
  isCacheExpired(cached: { timestamp: number }): boolean {
    const revalidateTime = getRevalidateTime() // Get from config
    return Date.now() - cached.timestamp > revalidateTime * 1000
  }
}

Compiler Workflow

Vue Component to HTML Compilation:

// packages/nuxt/src/core/compiler/vue-compiler.ts
export async function compileVueToHTML(component: VueComponent) {
  // 1. Parse Vue component
  const ast = parseVueComponent(component)

  // 2. Transform AST
  const transformedAst = transformAST(ast)

  // 3. Generate render function
  const renderFunction = generateRenderFunction(transformedAst)

  // 4. Create virtual DOM
  const vdom = renderFunction()

  // 5. Generate HTML string
  const html = generateHTMLFromVNode(vdom)

  return html
}

// Render function generation example
function generateRenderFunction(ast: ASTNode): Function {
  // 1. Process template directives
  const directives = processDirectives(ast.directives)

  // 2. Generate render code
  return new Function(`
    with(this) {
      return ${generateVNodeCode(ast)}
    }
  `)
}

Performance Optimization Source Code

Code Splitting Implementation:

// packages/nuxt/src/core/compiler/code-splitting.ts
export function applyCodeSplitting(component: VueComponent) {
  // 1. Analyze component dependencies
  const dependencies = analyzeDependencies(component)

  // 2. Group into chunks
  const chunks = groupDependencies(dependencies)

  // 3. Generate dynamic import code
  return generateDynamicImports(chunks)
}

// Dynamic import code generation example
function generateDynamicImports(chunks: Chunk[]) {
  return chunks.map(chunk => {
    return `
      const ${chunk.name} = () => import('${chunk.path}')
      __webpackChunkName: '${chunk.name}'
    `
  }).join('\n')
}

Lazy Loading Implementation:

// packages/nuxt/src/core/compiler/lazy-loading.ts
export function applyLazyLoading(component: VueComponent) {
  // 1. Identify lazy-loadable parts
  const lazyParts = identifyLazyParts(component)

  // 2. Wrap as async components
  const lazyComponents = lazyParts.map(part => {
    return defineAsyncComponent({
      loader: () => import(part.path),
      loadingComponent: part.loadingComponent,
      delay: part.delay,
      timeout: part.timeout
    })
  })

  // 3. Replace original components
  return replaceComponents(component, lazyComponents)
}

Module and Plugin Source Code

Module Loading and Initialization

Module Lifecycle Management:

// packages/nuxt/src/core/modules/lifecycle.ts
export class ModuleManager {
  private modules: NuxtModule[] = []

  // Load modules
  async loadModules() {
    // 1. Load built-in modules
    await this.loadBuiltInModules()

    // 2. Load project modules
    const modulePaths = await this.discoverModules()
    await this.loadProjectModules(modulePaths)

    // 3. Execute initialization
    await this.initializeModules()
  }

  // Initialize modules
  async initializeModules() {
    // Execute module setup sequentially
    for (const module of this.modules) {
      if (module.setup) {
        await module.setup({
          nuxt: this.nuxt,
          ...module.options
        })
      }
    }

    // Execute module hooks
    await this.runHooks('ready')
  }
}

Plugin Registration and Execution

Plugin System Implementation:

// packages/nuxt/src/core/plugins/manager.ts
export class PluginManager {
  private plugins: Plugin[] = []

  // Register plugin
  registerPlugin(plugin: Plugin) {
    // 1. Validate plugin structure
    if (!plugin.src && !plugin.mode) {
      throw new Error('Invalid plugin configuration')
    }

    // 2. Add to plugin list
    this.plugins.push(plugin)
  }

  // Execute plugins
  async runPlugins() {
    // Execute plugins sequentially
    for (const plugin of this.plugins) {
      if (plugin.mode === 'client') {
        await this.loadClientPlugin(plugin)
      } else if (plugin.mode === 'server') {
        await this.loadServerPlugin(plugin)
      } else {
        // Universal plugin
        await this.loadUniversalPlugin(plugin)
      }
    }
  }
}

Module and Plugin Communication

Communication Mechanism Implementation:

// packages/nuxt/src/core/communication/bus.ts
export class ModulePluginBus {
  private events: Record<string, Function[]> = {}

  // Module/plugin event subscription
  on(event: string, callback: Function) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  }

  // Module/plugin event emission
  emit(event: string, ...args: any[]) {
    if (this.events[event]) {
      this.events[event].forEach(callback => {
        callback(...args)
      })
    }
  }
}

// Provide communication bus in Nuxt context
export function useModulePluginBus() {
  return useContext().bus
}

Performance Optimization

Module Loading Optimization:

// packages/nuxt/src/core/modules/optimizer.ts
export class ModuleOptimizer {
  // Parallel module loading
  async loadModulesParallel(modulePaths: string[]) {
    // 1. Analyze module dependency graph
    const dependencyGraph = this.buildDependencyGraph(modulePaths)

    // 2. Topological sort to determine load order
    const loadOrder = this.topologicalSort(dependencyGraph)

    // 3. Parallel load of independent modules
    await this.parallelLoad(loadOrder)
  }

  // Code splitting optimization
  optimizeCodeSplitting() {
    // 1. Analyze module usage
    const usageStats = this.analyzeModuleUsage()

    // 2. Merge frequently used modules
    const mergedChunks = this.mergeFrequentlyUsedModules(usageStats)

    // 3. Generate optimized code splitting configuration
    return this.generateOptimizedConfig(mergedChunks)
  }
}

Security Strategies

Module Security Validation:

// packages/nuxt/src/core/security/module.ts
export class ModuleSecurity {
  // Validate module security
  async validateModule(modulePath: string) {
    // 1. Check module source
    if (!this.isTrustedSource(modulePath)) {
      throw new Error('Untrusted module source')
    }

    // 2. Scan for malicious code
    const scanResult = await this.scanForMaliciousCode(modulePath)
    if (scanResult.hasIssues) {
      throw new Error('Module contains potential security issues')
    }

    // 3. Validate dependencies
    const dependencyIssues = await this.checkDependencies(modulePath)
    if (dependencyIssues.length > 0) {
      throw new Error(`Module has vulnerable dependencies: ${dependencyIssues.join(', ')}`)
    }
  }

  // Permission control
  checkModulePermissions(module: NuxtModule, context: NuxtContext) {
    // 1. Check required permissions
    const requiredPermissions = module.meta.requiredPermissions || []

    // 2. Validate user permissions
    if (requiredPermissions.length > 0) {
      const userPermissions = context.user?.permissions || []
      const hasPermission = requiredPermissions.every(p => 
        userPermissions.includes(p)
      )

      if (!hasPermission) {
        throw new Error('Insufficient permissions for module')
      }
    }
  }
}
Share your love