Quick Refresher on Node.js
Explore how Node.js executes JavaScript outside the browser, organizes code using modules, and handles HTTP requests.
Before starting with Express.js, we must ensure we have a solid grasp of Node.js. Since Express builds on top of Node, understanding its runtime environment, module system, and core capabilities will make learning Express much smoother.
Let’s dive in!
Understanding the Node.js runtime
Node.js is a JavaScript runtime that lets you run JavaScript on servers, command line tools, and other environments outside the browser. It uses Chrome’s fast V8 engine under the hood to execute JavaScript. Unlike a browser environment, Node.js provides direct access to the operating system, file system, and network, making it a powerful tool for back-end development.
To handle multiple tasks efficiently, Node.js adopts a single-threaded, event-driven model that employs non-blocking I/O. This design choice allows it to process many requests concurrently without waiting for previous ones to complete.
Working with modules and npm
Node.js organizes code using modules, which help keep projects modular and maintainable. There are three types of modules:
Built-in modules: Predefined modules like
fs
,path
, andhttp
Custom modules: Our reusable code files
Third-party modules: Packages installed via
npm
Using a built-in module
Built-in Node.js modules provide functionality for various tasks. For example, the file system module fs
allows us to perform file operations, as shown below. These modules come preinstalled with Node.js, so we can use them directly without installing additional packages.
const fs = require('fs');const data = fs.readFileSync('example.txt', 'utf8');console.log(data);
Explanation:
Line 1: This imports the
fs
module, which provides file system operations.Line 3: This reads a file synchronously using
fs.readFileSync
, meaning execution pauses until the file is fully read. The'utf8'
argument specifies that the file should be interpreted as UTF-8 encoded text, which is the standard encoding for most text files.
Creating and using a custom module
Custom modules can be defined in separate .js
files within a project and imported wherever needed. In Node.js, a file becomes a module when it exports functionality that other files can use. To better understand how they work, let’s create a simple module that returns a greeting message.
const defaultGreeting = "Hello, there!";function greet(name) {return `Hello, ${name}!`;}module.exports = { greet, defaultGreeting };
Explanation:
In
greet.js
:Lines 1–3: These define
defaultGreeting
, a reusable constant, andgreet(name)
, a function that returns a personalized greeting.Line 7: This exports both
greet
anddefaultGreeting
usingmodule.exports
, allowing them to be imported into other files.
In
index.js
:Line 1: Imports both the
greet
function anddefaultGreeting
fromgreet.js
.Lines 3–4: Invoke the
greet
function and log the output. Also, logsdefaultGreeting
to show that it can be accessed independently.
Third-party package management with npm
Instead of writing all functionality from scratch, we can use third-party packages. Node.js comes with npm
(Node Package Manager), which helps install and manage third-party packages. Every project that uses npm
has a package.json
file, which keeps track of dependencies.
The package.json
file stores metadata about a Node.js project, including dependencies and scripts. This file ensures that the correct package versions are installed when sharing the project with others.
{"name": "my-project","version": "1.0.0","description": "A sample project","main": "index.js","type": "module","scripts": {"start": "node index.js"},"dependencies": {"express": "^4.18.2"}}
Here are some of the most commonly used fields in package.json
:
| Project name |
| Project version |
| Defines module type (module for ESM, default is CommonJS—we’ll see these shortly) |
| Custom commands (e.g., |
| Installed packages |
Installing and using third-party packages
Use the following command to install a third-party package (like lodash
):
npm install lodash
Follow the commands below to use it in the code:
const _ = require('lodash');console.log(_.capitalize('hello'));
Explanation:
Line 1: This imports the
lodash
library, a popular JavaScript utility library.Line 2: This uses
_.capitalize()
to capitalize the first letter of the string ‘hello’, demonstrating howlodash
simplifies common string operations.
Note: If
package.json
does not exist,lodash
will still install and function, but it won’t be recorded anywhere for future installs. This means that if another developer clones the project, they won’t automatically getlodash
unlesspackage.json
is present.
CommonJS vs. ES Modules in Node.js
Node.js supports two module systems: CommonJS (CJS) and ES Modules (ESM). Historically, CommonJS has been the default module system in Node.js. It uses require()
to import modules and module.exports
to export them. This approach remains well-suited for server-side development and is still widely used in many Node.js projects.
In contrast, ES Modules use import
and export
, and they load asynchronously, meaning they do not block code execution during imports. They also work natively in browsers and are fully supported in newer versions of Node.js.
Here’s a simple example demonstrating how to use import
and export
for modularizing code:
export const defaultGreeting = "Hello, there!";export function greet(name) {return `Hello, ${name}!`;};
Explanation:
greet.mjs
: We use theexport
keyword to make functions, variables, or objects available for use in other files.index.mjs
: We import both thegreet
function anddefaultGreeting
variable fromgreet.mjs
.
To use ES Modules in a Node.js project, we need to specify "type": "module"
in the package.json
file. This setting tells Node.js to interpret files using ES module syntax instead of CommonJS.
Side-by-side comparison
Here’s a quick comparison of the two module systems:
Feature | CommonJS (CJS) | ES Module (ESM) |
Default in Node.js? | Yes | No (must enable with |
Works in Browsers? | No | Yes |
Execution Style | Synchronous | Asynchronous |
Usage in Node.js | Older codebases, compatibility with existing tools | Recommended for modern applications |
Creating a simple HTTP server
Now that we have covered how Node.js handles modules and package management, let’s explore how we can use Node.js to create a basic web server. Node.js provides the http
module for handling HTTP requests.
{ "name": "my-project", "version": "1.0.0", "description": "A sample project", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.18.2" } }
Explanation:
Line 1: This imports the built-in
http
module.Line 3: This creates an HTTP server that listens for requests.
Line 4: This sets the response status code to 200, indicating that the request was successful. The content type is set to
text/plain
to specify that the response body contains plain text rather than HTML or JSON.Line 5: This sends back the response “Hello, World!”.
Line 8: The server listens on port 3000.
While this works, managing multiple routes with the http
module becomes cumbersome. Express.js simplifies this process significantly.
Key takeaways:
Node.js is a JavaScript runtime environment that executes code outside the browser using the V8 engine.
It follows a single-threaded, event-driven architecture with non-blocking I/O.
The module system in Node.js allows us to use built-in modules, third-party packages, and custom modules.
The
http
module enables us to create a basic web server, but it has limitations.
Exercise: Working with modules in Node.js
The following files have been pre-created for you: mathOperations.js
, index.js
, and package.json
. Your task is to complete the missing code in these files.
Task 1:
In mathOperations.js
, the following functions have been defined for you. Your task is to export them so they can be used in index.js
:
add(a, b)
: This returns the sum of two numbers.multiply(a, b)
: This returns the product of two numbers.
Task 2:
In index.js
:
Import the functions from
mathOperations.js
.Use them to perform calculations.
Print the results of calling both functions.
Run index.js
to verify the output.
// Task 1: Export the following functions...function add(a, b) {return a + b;}function multiply(a, b) {return a * b;}