Top Node.js Interview Questions and Answers (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:
-
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
-
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.
- If the file is in the same directory as the current script, use
-
Requiring JSON Files: You can use
require
to load JSON files directly. Therequire
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);
-
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. -
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
-
Exports: Each module in Node.js can expose functions, objects, or variables via the
module.exports
object. When yourequire
a module, you get whatever has been assigned tomodule.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!
-
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
andexport
syntax and allow for asynchronous loading. Node.js has added support for ES Modules, butrequire
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 yourpackage.json
.
import fs from 'fs'; // ES Module syntax
-
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.).
- The
Example of Using require
:
-
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'); });
-
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
-
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 themodule.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:
-
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).
-
Handling Requests: Middleware can perform actions such as logging requests, checking authentication, validating input, error handling, or serving static files.
-
Passing Control: Middleware functions can pass control to the next middleware or request handler by calling the
next()
function. If a middleware does not callnext()
, the request-response cycle will stop, and the client will not receive a response. -
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:
-
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'); });
-
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'); });
-
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'); });
-
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 thenext()
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'); });
- These middleware functions handle errors in the application. They typically take four arguments:
-
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:
-
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.
-
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.
Tags
- Node.js
- JavaScript
- Backend Development
- Asynchronous Programming
- Event Driven Architecture
- Event Loop
- Callbacks
- Promises
- Async/Await
- Streams
- Require
- Modules
- Middleware
- Express.js
- Error Handling
- Cluster Module
- Process.nextTick
- SetImmediate
- Concurrency
- Non Blocking I/O
- HTTP Module
- File System (fs) Module
- Node.js Interview Questions
- Node.js Advantages
- Node.js Performance
- Node.js Errors
- Callback Hell
- Server Side JavaScript
- Scalable Web Servers
- Node.js Architecture
- Node.js Event Emitters