Objectives - Node.js & Express Basics

Overview

Traditionally, developers only used the JavaScript language in web browsers. But, in 2009, Node.js was unveiled, and with it, the developer tool kit expanded greatly. Node.js gave developers the chance to use JavaScript to write software that, up to that point, could only be written using C, C++, Java, Python, Ruby, C#, and the like.

We will use Node to write server code. Specifically, web services that communicate with clients using the JavaScript Object Notation (JSON) format for data interchange.

Advantages of Node.js

  • Node.js uses the same programming language (JavaScript) and paradigm for both client and server. Using the same language, we minimize context switching and share code between the client and the server.
  • JavaScript is single-threaded, which removes the complexity involved in handling multiple threads.
  • JavaScript is asynchronous, which allows us to take full advantage of the processor it's running on. Taking full advantage of the processor is crucial because the node process will be running on a single CPU.
  • Using JavaScript gives us access to the npm repository. This repository is the largest ecosystem of valuable libraries (most free to use) in npm modules.

Disadvantages of Node.js

  • By strictly using JavaScript on the server, we cannot use the right tool (a particular language) for the job.
  • Because JavaScript is single-threaded, we can't take advantage of servers with multiple cores/processors.
  • Because JavaScript is asynchronous, it is harder to learn for developers that have only worked with languages that default to synchronous operations that block the execution thread.
  • In the npm repository, there are often too many packages that do the same thing. This excess of packages makes it harder to choose one and, in some cases, may introduce vulnerabilities into our code.

Core Concepts of Node.js Development

Event-Driven Architecture

Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices. This architecture allows Node.js to handle thousands of concurrent connections with a single server without introducing the burden of managing thread concurrency, which leads to deadlocks.

NPM (Node Package Manager)

NPM is the world's largest software registry with over 1 million packages, allowing developers to easily share and reuse code. It simplifies package installation, version management, and dependency management. NPM comes bundled with Node.js, making it immediately available once Node.js is installed.

Single-threaded Event Loop

Node.js processes incoming requests in a single thread, using non-blocking I/O calls to support thousands of concurrent connections without incurring the cost of thread context switching. The event loop is what allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded.

CommonJS Module System

Node.js implements the CommonJS module specification, making it easy to organize and reuse code across files and projects. This module system allows for encapsulation of code, creating more maintainable applications. With the require() function, developers can easily import functionality from other files or third-party packages.

Writing Web Servers with Node.js

To write a simple web server with Node.js:

  1. Use Node's HTTP module to abstract away complex network-related operations.
  2. Write the single request handler function to handle all requests to the server.

The request handler is a function that takes the request coming from the client and produces the response. The function takes two arguments: 1) an object representing the request and 2) an object representing the response.

This process works, but the resulting code is verbose, even for the simplest of servers. Also, note that when using only Node.js to build a server, we use a single request handler function for all requests.

Follow Along

Using only Node.js, let's write a simple web server that returns a message. Create a folder for the server and add an index.js file inside.

Next, add the following code to the index.js file:

const http = require("http"); // built in node.js module to handle http traffic

const hostname = "127.0.0.1"; // the local computer where the server is running
const port = 3000; // a port we'll use to watch for traffic

const server = http.createServer((req, res) => {
    // creates our server
    res.statusCode = 200; // http status code returned to the client
    res.setHeader("Content-Type", "text/plain"); // inform the client that we'll be returning text
    res.end("Hello World from Node\n"); // end the request and send a response with the specified message
});

server.listen(port, hostname, () => {
    // start watching for connections on the port specified
    console.log(`Server running at http://${hostname}:${port}/`);
});

Now navigate to the folder in a terminal/console window and type: node index.js to execute your file. A message that reads "Server running at http://127.0.0.1:3000" should be displayed, and the server is now waiting for connections.

Open a browser and visit: http://localhost:3000. localhost and the IP address 127.0.0.1 point to the same thing: your local computer. The browser should show the message: "Hello World from Node". There you have it, your first web server, built from scratch using nothing but Node.js.

Challenge

Write a paragraph about what Node.js is and explain at least 3 of its core features.

Consider addressing the following points in your response:

  • What problem does Node.js solve in web development?
  • How does Node.js handle asynchronous operations?
  • What are the advantages of using JavaScript on both client and server?
  • How does the npm ecosystem contribute to Node.js development?

Additional Resources