DEV Community

Cover image for JavaScript on the Server: Node.js
Achal Tiwari
Achal Tiwari

Posted on

JavaScript on the Server: Node.js

What is Node.js?

Let's dive into Node.js! This article covers many concepts, so grab your favorite coffee or tea, sit back, and let's get started. If you're in a rush, feel free to bookmark it for later. Let's begin!

Image description

Introduction to Node.js

Node.js is an open-source, cross-platform JavaScript runtime environment that lets you run JavaScript code on the server side. Here’s why it’s important and how it works:

  • Node.js is an open-source server environment
  • An open source server environment is a computer system that processes requests via HTTP
  • Node.js is a cross-platform, open-source JavaScript runtime environment To understand the magic of Node.js, let's compare it with PHP or ASP in handling file requests:
Traditional PHP or ASP Approach:
  • Sends the task to the computer's file system.
  • Waits while the file system opens and reads the file.
  • Returns the content to the client.
  • Ready to handle the next request. ##### Node.js Approach:
  • Sends the task to the computer's file system.
  • Ready to handle the next request.
  • When the file system has opened and read the file, the server returns the content to the client. It runs on a single thread using non-blocking, asynchronous programming, which makes it very memory-efficient.

Understanding Node.js Modules

Modules in Node.js are like libraries in JavaScript. Here are the types of modules:

  • Core Modules: Built into Node.js and available without any additional installation.
  • Local Modules: Created within your project.
  • Third-Party Modules: Available through the npm registry and can be installed using npm.

Image description

Core Modules

Core modules are part of the Node.js framework. Some examples include:

  • fs: File System module for interacting with the file system.
  • http: HTTP module for creating web servers.
  • path: Path module for handling and transforming file paths.
  • os: Operating System module for fetching OS-related information.
Example: Using the fs Module
const fs = require('fs');
// Reading a file
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(data);
});
Enter fullscreen mode Exit fullscreen mode

Local Modules

  • They can be a single file or a collection of files organized in a directory.
Example: Creating and Using a Local Module

Create a Local Module

// maths.js
function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

module.exports = { add, subtract };

Enter fullscreen mode Exit fullscreen mode

Use the Local Module

// app.js
const math = require('./math');

console.log(math.add(5, 3)); // Output: 8
console.log(math.subtract(5, 3)); // Output: 2
Enter fullscreen mode Exit fullscreen mode

Third-Party Modules

Example: Installing and Using a Third-Party Module

Install the Module

npm install lodash
Enter fullscreen mode Exit fullscreen mode

Use the Installed Module

const _ = require('lodash');

const array = [1, 2, 3, 4, 5];
const reversedArray = _.reverse(array.slice());
console.log(reversedArray); // Output: [5, 4, 3, 2, 1]
Enter fullscreen mode Exit fullscreen mode

Module Caching

Node.js caches modules after they are loaded for the first time.
This means that subsequent require calls for the same module will return the cached version.

Node.js HTTP Module

  • The http module in Node.js is a core module that provides functionality to create web servers and handle HTTP requests and responses.

Image description

const http = require('http');

// Using the `http.createServer()` method to create an HTTP server
const server = http.createServer((req, res) => {  // a callback function to handle incoming requests and send responses.
  res.statusCode = 200; // HTTP status code
  res.setHeader('Content-Type', 'text/plain'); // Set response headers
  res.end('Hello, World!\n'); // Send response
});

// Make the server listen on port 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Server is running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode

Handling Different Request Methods

HTTP servers can handle different types of requests, such as GET, POST, PUT, and DELETE.
Important Methods:

  1. request.on(event, callback):
    • This method is used to set up event listeners for various events that may occur during an HTTP request.
    • The event parameter specifies the event to listen for, such as 'data' for when a chunk of data is received, or 'end' for when the entire response has been received.
    • The callback function is called when the specified event occurs.
  2. request.end([data], [encoding], [callback]):
    • This method is used to send the request to the server.
    • It finalizes the request, so no more data can be written to the request.
    • Optionally, you can pass data to be sent in the request body, encoding to specify the encoding of the data, and a callback function that will be called when the request has been sent.
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'GET') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Received a GET request\n');
  } 
  else if (req.method === 'POST') {\
    let body = '';
    req.on('data', chunk => {
    // chunk will be a buffer like <Buffer 6d 65 73 ... >, 
    // therefore we convered it to String
      body += chunk.toString(); // Convert Buffer to string
    });

    req.on('end', () => {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'application/json');
      res.end(`Received a POST request with body: ${body}\n`);
    });
  } 
  else {
    res.statusCode = 405; // Method Not Allowed
    res.setHeader('Content-Type', 'text/plain');
    res.end('Method Not Allowed\n');
  }
});

// Listen on port 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Server is running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode

We can use test this code by the use of curl command, to send a post request to our page.

Events

Key Concepts
  1. EventEmitter:
    • Core of Node asynchronous event-driven architecture
    • It is a module that facilitates communication/interaction between objects in Node.
    • Emitter objects emit named events that cause previously registered listeners to be called.
    • So, an emitter object basically has two main features:
      • Emitting name events.
      • Registering and unregistering listener functions.

Image description

Creating an event
const EventEmitter = require('events');
// Creating an event
const myEmitter = new EventEmitter();

// Define an event listener
const greetListener = (name) => {
  console.log(`Hello, ${name}!`);
};

myEmitter.on('greet', greetListener);

// Emit the event, this will emit the event named 'greet'
// passing 'World' as an argument
myEmitter.emit('greet', 'World');

console.log(myEmitter.listenerCount('greet')); // 1

// Removing the listener
myEmitter.off('greet', greetListener);

// Now, even if you emit the event, nothing will happen
myEmitter.emit('greet', 'World');

console.log(myEmitter.listenerCount('greet')); // 0
console.log(myEmitter.rawListeners('greet')); // []

//-----------Output----------
Hello, World!
1
[ [Function: greetListener] ]
0
[]
Enter fullscreen mode Exit fullscreen mode
Built-in Events
const http = require('http');
const server = http.createServer((req, res) => {
  res.end('Hello, World!');
});

server.on('request', (req, res) => {
  console.log(`Request received: ${req.url}`);
});

server.listen(3000, () => {
  console.log('Server listening on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

Serving Static Files

  • This code will display your image1.png when at localhost:3000/ or 127.0.0.1:3000
const http = require('http');
const fs = require('fs');
const path = require('path');

// Create the server
const server = http.createServer((req, res) => {
  const filePath = path.join(__dirname, req.url === '/' ? 'image1.png' : req.url);
  const extname = path.extname(filePath);
  let contentType = 'text/html';

  // Set content type based on file extension
  switch (extname) {
    case '.js':
      contentType = 'text/javascript';
      break;
    case '.css':
      contentType = 'text/css';
      break;
    case '.json':
      contentType = 'application/json';
      break;
    case '.png':
      contentType = 'image/png';
      break;
    case '.jpg':
      contentType = 'image/jpg';
      break;
  }

  // Read and serve the file
  fs.readFile(filePath, (err, content) => {
    if (err) {
      if (err.code === 'ENOENT') {
        // File not found
        res.statusCode = 404;
        res.setHeader('Content-Type', 'text/html');
        res.end('<h1>404 Not Found</h1>');
      } else {
        // Server error
        res.statusCode = 500;
        res.setHeader('Content-Type', 'text/html');
        res.end('<h1>500 Server Error</h1>');
      }
    } else {
      // Serve the file
      res.statusCode = 200;
      res.setHeader('Content-Type', contentType);
      res.end(content);
    }
  });
});

// Listen on port 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Server is running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode
URL Module
var url = require('url');  
var adr = 'http://localhost:8080/default.htm?year=2017&month=february';  
var q = url.parse(adr, true);  

console.log(q.host); //returns 'localhost:8080'  
console.log(q.pathname); //returns '/default.htm'  
console.log(q.search); //returns '?year=2017&month=february'  

var qdata = q.query; //returns an object: { year: 2017, month: 'february' }  
console.log(qdata.month); //returns 'february'
Enter fullscreen mode Exit fullscreen mode
Query using URL Parameters
const http = require('http');
const url = require('url');

const server = http.createServer((req, res) => {
  // Parse the URL
  const parsedUrl = url.parse(req.url, true);
  // Extract the pathname (e.g., '/filename.ext')
  const pathname = parsedUrl.pathname;
  // Extract the filename from the pathname
  const filename = pathname.substring(pathname.lastIndexOf('/') + 1);
  // Correctly display the filename with spaces and other special characters
  const decodedFilename = decodeURIComponent(filename); 

  // Set the response header and status code
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/html');

  // Send the response
  res.end(`<h1>Filename: ${decodedFilename}</h1>`);
});

// Listen on port 3000
server.listen(3000, '127.0.0.1', () => {
  console.log('Server is running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode

Open your web browser and navigate to http://127.0.0.1:3000/filename.ext (replace filename.ext with any filename you want to test). The server will display the filename extracted from the URL on the webpage.

Thank you for sticking through this long read. If you have any questions or need further clarification, feel free to reach out in the comments. Happy coding!

Top comments (0)