Top Node.js Interview Questions and Answers (2025)

author image Hirely
at 08 Jan, 2025

Question: What is the require function in Node.js?

Answer:

In Node.js, require is a built-in function used to import modules, JSON files, or local files into a Node.js application. It is part of the CommonJS module system, which allows you to organize code into reusable modules.

The require function loads the module or file, evaluates it, and returns the exports of that module. This mechanism is what allows you to split your Node.js application into smaller, manageable components (modules).

Key Points about the require function:

  1. Importing Built-in Modules: Node.js provides a set of built-in modules (such as fs, http, path, etc.) that you can require directly by their name without the need to specify file paths. For example:

    const fs = require('fs');  // Imports the fs (file system) module
    const http = require('http');  // Imports the http module
  2. Importing Local Modules: You can also use require to load custom or local modules. In this case, you need to provide the relative or absolute path to the file.

    const myModule = require('./myModule');  // Requires a local module (myModule.js)
    • If the file is in the same directory as the current script, use ./.
    • If the file is in a different directory, use ../ or specify the full path.
    • Node.js will automatically append .js, .json, and .node file extensions to the path if not specified.
  3. Requiring JSON Files: You can use require to load JSON files directly. The require function will automatically parse the JSON content into a JavaScript object.

    const config = require('./config.json');  // Requires a JSON file and parses it
    console.log(config);
  4. Requiring Node.js Addons: You can also require compiled C++ Addons (i.e., .node files) created using the Node.js native add-on API, though this is less common for everyday applications.

  5. Caching:

    • Node.js caches modules that have been loaded once, so when you require a module multiple times, Node.js does not reload or re-evaluate the module; it returns the cached version. This behavior helps improve performance.
    • If you modify a module after it has been loaded, those changes will not be reflected in the already-loaded modules unless the cache is cleared.

    You can clear the cache manually if needed:

    delete require.cache[require.resolve('./myModule')];  // Clear cache of the module
  6. Exports: Each module in Node.js can expose functions, objects, or variables via the module.exports object. When you require a module, you get whatever has been assigned to module.exports.

    Example of a simple module (myModule.js):

    // myModule.js
    module.exports = function() {
        console.log('Hello from myModule!');
    };

    You can then require this module in another file:

    const myModule = require('./myModule');
    myModule();  // Outputs: Hello from myModule!
  7. require vs. import (ES Modules):

    • require is part of the CommonJS module system, which is synchronous and was the original module system used in Node.js.
    • ES Modules (ESM), introduced more recently, use import and export syntax and allow for asynchronous loading. Node.js has added support for ES Modules, but require remains the standard for many existing Node.js applications.
    • To use ES modules in Node.js, you need to either use .mjs file extensions or set "type": "module" in your package.json.
    import fs from 'fs';  // ES Module syntax
  8. require in the Context of Node.js:

    • The require function is synchronous, meaning it blocks the execution of further code until the required module is fully loaded. This is fine for most use cases, as Node.js is single-threaded and can efficiently handle I/O operations.
    • require is used to load both built-in Node.js modules as well as external modules installed via npm (e.g., express, lodash, etc.).

Example of Using require:

  1. Using Built-in Modules:

    // Import the HTTP module to create a server
    const http = require('http');
    
    // Create a basic HTTP server
    const server = http.createServer((req, res) => {
        res.write('Hello, world!');
        res.end();
    });
    
    // Start the server on port 3000
    server.listen(3000, () => {
        console.log('Server is running on http://localhost:3000');
    });
  2. Using Local Modules:

    • math.js:
    // math.js (module file)
    module.exports.add = (a, b) => a + b;
    module.exports.subtract = (a, b) => a - b;
    • main.js:
    const math = require('./math');
    
    console.log(math.add(2, 3));  // Outputs: 5
    console.log(math.subtract(5, 2));  // Outputs: 3
  3. Using JSON Files:

    // config.json
    {
        "port": 3000,
        "env": "production"
    }
    const config = require('./config.json');
    
    console.log(config.port);  // Outputs: 3000
    console.log(config.env);   // Outputs: production

Summary:

  • The require function is used to load modules, JSON files, and local files in Node.js.
  • It is part of the CommonJS module system and is synchronous.
  • When you require a module, Node.js reads the file, evaluates it, and returns the module.exports object.
  • It helps structure your application by allowing you to separate concerns into different files, making the code easier to maintain and test.

Question: What is Middleware in Node.js?

Answer:

In Node.js, middleware refers to functions that are executed during the request-response cycle in a web server (typically in the context of HTTP requests). Middleware functions sit between the raw incoming request and the final request handler, modifying the request, response, or both, or performing some action before passing control to the next middleware in the stack.

Middleware is often used in Express.js, the popular web framework for Node.js, but the concept of middleware is applicable in various frameworks and libraries.

Key Characteristics of Middleware:

  1. Request and Response Modifications: Middleware can modify the request object (e.g., adding properties, parsing body data) or the response object (e.g., adding headers, modifying response data).

  2. Handling Requests: Middleware can perform actions such as logging requests, checking authentication, validating input, error handling, or serving static files.

  3. Passing Control: Middleware functions can pass control to the next middleware or request handler by calling the next() function. If a middleware does not call next(), the request-response cycle will stop, and the client will not receive a response.

  4. Chaining Functions: Middleware functions are executed in the order they are defined. Each function can either terminate the request-response cycle (by sending a response) or pass control to the next function in the chain.

Types of Middleware:

  1. Application-Level Middleware:

    • These are middleware functions that are bound to a specific instance of the application. They can be applied to all routes or to specific routes.
    • Example:
      const express = require('express');
      const app = express();
      
      // Application-level middleware to log every request
      app.use((req, res, next) => {
          console.log(`${req.method} ${req.url}`);
          next();  // Pass control to the next middleware
      });
      
      app.get('/', (req, res) => {
          res.send('Hello, world!');
      });
      
      app.listen(3000, () => {
          console.log('Server is running on port 3000');
      });
  2. Router-Level Middleware:

    • These middleware functions are specific to a particular router or set of routes within the application.
    • Example:
      const express = require('express');
      const router = express.Router();
      
      // Middleware for a specific router
      router.use((req, res, next) => {
          console.log('Request received by the router');
          next();
      });
      
      router.get('/home', (req, res) => {
          res.send('Home route');
      });
      
      router.get('/about', (req, res) => {
          res.send('About route');
      });
      
      const app = express();
      app.use('/myapp', router);
      app.listen(3000, () => {
          console.log('Server is running on port 3000');
      });
  3. Built-in Middleware:

    • Express provides several built-in middleware functions to handle common tasks, such as serving static files, parsing JSON bodies, or handling URL-encoded data.
    • Examples:
      • express.static(): Serves static files like images, CSS, and JavaScript.
      • express.json(): Parses incoming requests with JSON payloads.
      • express.urlencoded(): Parses incoming requests with URL-encoded data.
    const express = require('express');
    const app = express();
    
    // Built-in middleware to parse JSON
    app.use(express.json());
    
    // Built-in middleware to serve static files
    app.use(express.static('public'));
    
    app.listen(3000, () => {
        console.log('Server running on port 3000');
    });
  4. Error-Handling Middleware:

    • These middleware functions handle errors in the application. They typically take four arguments: (err, req, res, next). If an error occurs in any middleware, it is passed to the error-handling middleware via the next() function.
    • Example:
      const express = require('express');
      const app = express();
      
      // Error-handling middleware
      app.use((err, req, res, next) => {
          console.error(err.stack);
          res.status(500).send('Something went wrong!');
      });
      
      app.listen(3000, () => {
          console.log('Server is running on port 3000');
      });
  5. Third-party Middleware:

    • You can also use third-party middleware, which are packages developed by the community to handle common tasks, such as authentication, logging, and data validation.
    • Examples include:
      • morgan (for HTTP request logging)
      • cors (for Cross-Origin Resource Sharing)
      • body-parser (for parsing incoming request bodies)

    To use third-party middleware:

    const express = require('express');
    const morgan = require('morgan');
    const app = express();
    
    // Use morgan to log HTTP requests
    app.use(morgan('dev'));
    
    app.get('/', (req, res) => {
        res.send('Hello, world!');
    });
    
    app.listen(3000, () => {
        console.log('Server is running on port 3000');
    });

How Middleware Works:

Middleware functions in Express (and similar frameworks) are executed in the order they are defined. The request is passed from one middleware to the next until it reaches the route handler or the response is sent back to the client.

  • When a request comes in, it goes through each middleware in the stack.
  • If a middleware calls next(), the request is passed to the next middleware.
  • If a middleware sends a response (using res.send(), res.json(), res.status(), etc.), the request-response cycle ends, and no further middleware is processed.

Example of Middleware Usage:

const express = require('express');
const app = express();

// Middleware to check if a user is authenticated
function checkAuth(req, res, next) {
    const isAuthenticated = false;  // Just an example
    if (!isAuthenticated) {
        return res.status(401).send('Unauthorized');
    }
    next();  // Proceed to the next middleware or route handler
}

// Apply middleware to a specific route
app.get('/profile', checkAuth, (req, res) => {
    res.send('This is the profile page');
});

// Global middleware for logging requests
app.use((req, res, next) => {
    console.log(`Request received: ${req.method} ${req.url}`);
    next();
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

Middleware Flow:

  1. Request Handling:

    • The request comes into the server.
    • Middleware functions process the request (logging, parsing data, checking authentication, etc.).
    • The request may pass through many middleware functions before reaching the route handler.
  2. Final Response:

    • Once all middleware has been processed, the route handler sends a response to the client (or stops further processing).
    • If an error occurs, it can be caught by an error-handling middleware.

Conclusion:

Middleware in Node.js, especially within frameworks like Express, is a critical concept for organizing and handling various aspects of the request-response cycle. It enables you to modularize common functionality (e.g., authentication, logging, parsing) into reusable components, making your application more maintainable and scalable. By using middleware effectively, you can add functionality to your application without repeating code and improve the overall structure of your app.

Read More

If you can’t get enough from this article, Aihirely has plenty more related information, such as Node.js interview questions, Node.js interview experiences, and details about various Node.js job positions. Click here to check it out.

Related Posts

Trace Job opportunities

Hirely, your exclusive interview companion, empowers your competence and facilitates your interviews.

Get Started Now