What is Node.js? A beginner's introduction to JavaScript runtime

What is Node.js? A beginner's introduction to JavaScript runtime

11 mins read
Oct 26, 2023
Share
editor-page-cover
Content
What is Node.js?
Fundamentals of Node.js
Console
Buffer
File System and the Event Loop
Streams, Piping, and Asynchronous Patterns
File read stream example
Piping streams
Asynchronous patterns
Event Driven Programming
Globals
Modules and ES / CommonJS Module Systems
How to build a basic Node.js server
Step 1: Install Node.js and NPM
Step 2: Create a file
Step 3: Run your Node.js program
HTTP Server, Routing, and Middleware Basics
What to learn next

Key Takeaways:

  • Node.js is a JavaScript Runtime Environment: It allows developers to execute JavaScript code outside of a web browser, enabling server-side scripting and building backend applications.

  • Event-Driven, Non-Blocking I/O Model: Node.js uses an event loop and asynchronous programming to handle multiple concurrent operations without blocking the main thread.

  • Rich Ecosystem with npm: Comes with Node Package Manager (npm), hosting over 2 million packages.

  • Simple to Create a Basic Server: With minimal code, you can set up a Node.js server to handle HTTP requests and serve different endpoints.

  • Part of Popular Web Development Stacks: Part of stacks like MERN, MEAN, and MEVN, allowing full-stack JavaScript development across frontend and backend.

Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside of a web browser. Node.js is popular among beginners due to its lightweight runtime, and it is used by many big companies like Netflix and Uber.

When we typically think of JavaScript, our mind tends to go to web development. Until Node.js came along, running JavaScript outside of a browser was not a common practice. When we write a backend server and database, Node.js is a popular choice because we can run our code as a standalone application rather than something that can only be evaluated in a browser environment.

Node.js is an important tool for any JavaScript developer to understand. So, today, we’ll introduce you to Node.js and show you how to get started with a project.

What is Node.js?#

Node.js is an open-source, cross-platform JavaScript runtime environment used for executing JavaScript code outside of a web browser.

Node.js is a great JavaScript runtime for beginners because it works great for data-intensive applications, like streaming and real-time apps, and Node.js makes it easy to start building the back-end.

Node.js allows us to use JavaScript everywhere and on any browser, including MacOS, Linux, and Windows. When we say everywhere, we mean the front-end, the middle-ware, and the back-end. Node.js is, therefore, part of some very popular web development stacks, such as the MERN stack, MEVN stack, and MEAN stack.

There are a number of characteristics that make Node.js what it is:

  • Google Chrome V8 JavaScript Engine: This runtime environment is built on the Google Chrome V8 JavaScript runtime engine. In the same way a Java Virtual Machine translates bytecode, the Chrome V8 JavaScript engine takes JavaScript and makes it executable.
  • Modules/Packages: Node.js has npm, a node package manager, with a library of over two million packages to help get your project or application off the ground with efficiency and ease.
  • Event Driven, Single-Threaded I/O Model: JavaScript relies on user interactions or events to run. In most cases, code is run synchronously. Server requests and other such asynchronous tasks rely on a system of promises or async/await functions.

Fundamentals of Node.js#

Now that we know what Node.js is, let’s explore the fundamentals of this tool.

Console#

The console is a module provided by Node.js that is akin to the JavaScript console in the browser when you inspect a webpage. The console has methods that are available for us to use for debugging purposes.

  • console.log(): Frequently used to log some sort of output.
  • console.warn(): Explicitly delivers a warning to the console.
  • console.error(): Explicitly delivers an error message to the console. You can log an error as a string or as an object. If logged as a new Error(), a traceback will be included as part of the message.
  • console.trace(): Logs a traceback when an error occurs in your code. Gives line number and column number of the file that the error probably occurred.

Buffer#

The Buffer class in Node.js is used for handling raw binary data directly. Due to its low-level nature, as web developers we will rarely actually use the Buffer class directly.

Let’s take a look at a few methods that the Buffer class provides.

Node.js
// Allocate a buffer of length 5, filled with zeros by default
const buf1 = Buffer.alloc(5);
console.log(buf1);
// Write a string to the buffer
buf1.write('abc');
console.log(buf1);
// Read the content of the buffer as a string
console.log(buf1.toString()); // Outputs: 'abc'
// Create a buffer from an array of values
const buf4 = Buffer.from([256, 6.5, -255, '7']);
console.log(buf4); // Truncated values [0, 6, 1, 7]

File System and the Event Loop#

The file system (fs) module allows us to interact with files in Node.js. There are synchronous and asynchronous methods that can be used to read or write to a file using the fs module. In contrast to using console or the Buffer class, we need to import the fs module into the file that we would like to use in order to get it to work.

Asynchronous Example:

The code example below shows how the readFile, an asynchronous method, works. Notice that the last argument in the method is a callback function whose first argument is an error. By definition this callback will always pass in the error first before the data.

The asynchronous nature of the readFile method doesn’t block other functions or lines of code from running.

Node.js
Files
const fs = require('fs')
fs.readFile('data.txt', 'utf-8', (err, data) => {
if (err) {
console.error(err)
return
}
let array = data.split('\n')
//props are id, first_name, last_name, email, gender and ip_address
let mapped = array.map(person => {
let new_person = person.split(',');
return new Object({
id: new_person[0],
first_name: new_person[1],
last_name: new_person[2],
email: new_person[3],
gender: new_person[4],
ip: new_person[5]
})
});
console.log(mapped)
});
console.log("Hit!")

Synchronous Example:

The synchronous method, readFileSync, however, blocks other lines of code from running until the file is finished reading. Here’s an example:

Node.js
Files
const fs = require('fs')
try {
const data = fs.readFileSync('data.txt', 'utf-8')
let array = data.split('\n')
//props are id, first_name, last_name, email, gender and ip_address
let mapped = array.map(person => {
let new_person = person.split(',');
return new Object({
id: new_person[0],
first_name: new_person[1],
last_name: new_person[2],
email: new_person[3],
gender: new_person[4],
ip: new_person[5]
})
});
console.log(mapped)
} catch (err) {
console.error(err)
}
console.log("Hit!")

Try placing a console.log(“Hit!”) after the function to see when the console is actually logged. Is there a difference between the two functions? What is it?

The readFile function will start the function and then immediately move to the rest of the code before the function completes and prints out the contents of our array. So you should see something like:

Hit!
 
[
 {
   id: '1',
   first_name: 'Annabell',
   last_name: 'Cicconetti',
   email: 'acicconetti0@example.com',
   gender: 'Female',
   ip: '219.207.16.2'
 },
 etc…
]

This asynchronous behavior is made possible by the Node.js event loop, which handles asynchronous operations efficiently. When readFile is called, Node.js offloads the file reading operation and continues executing the rest of the code. Once the file is read, the event loop returns to execute the callback function, ensuring non-blocking I/O.

In contrast, the console.log(“Hit!”) won’t run until after the readFileSync function is finished:

[...{
   id: '37',
   first_name: 'Arnoldo',
   last_name: 'Eakly',
   email: 'aeakly10@live.com',
   gender: 'Male',
   ip: '189.110.238.26'
 },
 {
   id: '38',
   first_name: 'Janis',
   last_name: 'Didball',
   email: 'jdidball11@shinystat.com',
   gender: 'Female',
   ip: '105.74.199.165'
 }
]
Hit!

Writing to files is done in a very similar fashion, but the functions are called writeFile() and writeFileSync().

With Node.js, dealing with files is fairly simple to do with the fs module.

Streams, Piping, and Asynchronous Patterns#

Node’s streaming APIs let you process large data (files, network, pipes) piece by piece instead of loading everything into memory.

File read stream example#

const fs = require('fs');
const readStream = fs.createReadStream('large.txt', { encoding: 'utf8' });

readStream.on('data', chunk => {
  console.log('Received chunk of size', chunk.length);
});

readStream.on('end', () => {
  console.log('Done reading');
});

Piping streams#

You can pipe a readable stream into a writable stream:

const { createReadStream, createWriteStream } = require('fs');
createReadStream('in.txt').pipe(createWriteStream('out.txt'));

When using network responses, you can pipe streams directly to HTTP:

const http = require('http');
const fs = require('fs');

http.createServer((req, res) => {
  const rs = fs.createReadStream('index.html');
  rs.pipe(res);
}).listen(3000);

Asynchronous patterns#

Compare callback, Promise, and async/await styles for clarity and flexibility:

// callback style
fs.readFile('file.txt', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// promise style
fs.promises.readFile('file.txt')
  .then(data => console.log(data))
  .catch(err => console.error(err));

// async/await
async function readIt() {
  try {
    const data = await fs.promises.readFile('file.txt');
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}
readIt();

These patterns let you manage asynchronous behavior more cleanly and efficiently across different parts of your Node.js applications.

Event Driven Programming#

Much of Node.js is built to be event-driven. When a user clicks on an interface or types in a form, an event is triggered to happen and then something occurs as a result. To attach a function or set of functions to a specific event is known as registering an event listener. When the event occurs, the event listener executes the attached callback function. Take this example:

Node.js
const EventEmitter = require('events');
const emitter = new EventEmitter();
const handleEvent = (str) => {
console.log(`================ ${str}`);
console.log("handleEvent fired! An event has happened!");
console.log("end of event")
}
emitter.on('load event', () => handleEvent("load"));
emitter.on('hello event', () => handleEvent("hello"));
emitter.emit('load event');
emitter.emit('hello event')

In this code example, we are importing the events module. Next, we create a new EventEmitter and assign it to the variable emitter. In this particular example, we created a handleEvent function that will serve as a callback function that will console.log some things.

The EventEmitter class has several methods we can use. One method that is used to register an event listener is the EventEmitter.on() function.

The event listener will fire the callback function when the associated event is emitted. The first argument passed into the function is the name of the event and the second is the callback function that tells us how to handle the event.

In this particular example, there are two events being emitted. When we run the code above, we should get:


================ load
handleEvent fired! An event has happened!
end of event
================ hello
handleEvent fired! An event has happened!
end of event
true

The emit method triggers the registered event listener which then invokes the handleEvent callback function.

Globals#

Global objects are available in every module, so they can be used without importing a specific module. The Buffer class, for example, is defined as a global in Node.js. Some other common global objects are:

  • The console object is used to print to stdout and stderr.
  • Timer functions, such as setImmediate, setInterval, and setTimeout, are also globals.
  • The process object is also global.

In a browser, the top-level scope is the global scope. But in Node.js, the top-level scope is the module scope, and each file is considered a separate module.

In Node.js, the global object can be used to see whatever is available in the global scope. Run the code below to see an example.

Node.js
console.log(global)

Modules and ES / CommonJS Module Systems#

To build real applications, you’ll organize code across files using modules.
Node.js originally used CommonJS modules:

// util.js
function greet(name) {
  return `Hello, ${name}!`;
}
module.exports = { greet };

// index.js
const { greet } = require('./util');
console.log(greet('Alice'));

With newer versions, Node also supports ES modules (via .mjs files or "type": "module" in package.json):

// util.mjs
export function greet(name) {
  return `Hello, ${name}!`;
}

// index.mjs
import { greet } from './util.mjs';
console.log(greet('Bob'));

Understanding module resolution helps you avoid relative path errors and circular dependencies.
Also, Node’s module caching ensures that require or import calls are fast and idempotent, improving runtime efficiency.

How to build a basic Node.js server#

Let’s learn how to get started with Node.js by creating a simple Node.js file. In this example, we will be setting up our computer to work as a server!

Step 1: Install Node.js and NPM#

First, you need to go to the site Node.js site and download the files.

Follow the installation prompts and restart your machine for best results.

Another way you can install Node.js is to use a package manager.

Then, test that it’s working by printing the version using the following command:

> node -v

You should also test npm by printing the version using the following command:

> npm -v

Step 2: Create a file#

Once you have installed Node.js properly, create a Node.js file. In this example, we have named it first.js. We then add the following code and save the file on your computer.

var http = require('http');

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.end('Hello World!');
}).listen(8080);

This code is essentially telling the computer to print “Hello World!” when accessed on port 8080.

Step 3: Run your Node.js program#

This file needs to then be run by Node.js. Do this by starting your command line interface, writing node first.js, and clicking enter:

node first.js

Awesome! Now your computer is set up as a server, so when you accesses the computer on port 8080, the “Hello World!” message will print.

To see this in real time, open your browser, and type: http://localhost:8080.

HTTP Server, Routing, and Middleware Basics#

You can use Node.js’s built-in http module to create a basic web server and handle routing.
Here’s a quick example:

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.url === '/hello') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Hello from Node.js');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Not found');
  }
});

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

For slightly more structure, you can implement a simple middleware pattern:

const middlewares = [];

function use(fn) {
  middlewares.push(fn);
}

function handle(req, res) {
  let idx = 0;
  function next() {
    const middleware = middlewares[idx++];
    if (middleware) middleware(req, res, next);
  }
  next();
}

// usage
use((req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
});
use((req, res) => {
  res.writeHead(200);
  res.end('Hi!');
});

This pattern foreshadows frameworks like Express.
A strong “What is Node.js” guide should include this to show how HTTP handling flows in raw Node.js before abstraction layers are introduced.

What to learn next#

Congrats! You know the basics of Node.js, its fundamental tools, and how to start a Node.js file. The next steps are to master Node.js modules, the HTTP Modules, File system, and NPM dependencies.

A good next step would be to learn the following concepts of Node.js:

  • Node.js and OS
  • Node.js REPL
  • Packages
  • How to publish a package
  • How to build a functing app
  • Node.js and MySQL

To get started with these advanced topics, check out the following course.


Learn Node.js: The Complete Course for Beginners

Cover
Learn Node.js: The Complete Course for Beginners

Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside of a web browser. This course is your guide for learning the fundamentals of Node.js. In this course, you'll start by understanding the inner workings of Node.js. More specifically, you’ll explore its features, how event loops work, and how multithreading works. You’ll then move on to the fundamentals of Node.js like file systems, global objects, and the Buffer class. In the latter half of the course, you’ll explore more advanced concepts like modules, events, and packages. At the end of this course, you will get hands-on with Node.js and create your own food delivery web application. By the end of this course, you will have a new, in-demand skill to put on your resume and a cool project to add to your portfolio.

7hrs
Beginner
37 Playgrounds
4 Quizzes

This course covers all these topics and more in detail. You’ll explore advanced concepts like modules, events, and packages. At the end of this course, you will get hands-on with Node.js and create your own food delivery web application.

Furthermore, Educative provides projects for hands-on learning, where you can quickly grasp a technology by taking a few guided projects.

To get hands on practice with Node.js, check out the hands-on project Build a Telegram Bot in Node.js for Web Page Change Detection, where you will write a Node.js script to detect changes in a website and be notified of them via Telegram.


Frequently Asked Questions

What is Node.js?

Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside a web browser. This feature allows developers to use JavaScript to build backend server applications, making it a key component of full-stack JavaScript development.

What is the main function of Node.js?

Node.js is a runtime environment that allows for the execution of JavaScript code on the server-side. It is commonly used to develop scalable network applications and is well-suited for data-intensive real-time applications.

What are the features of Node.js?

  • Asynchronous and Non-blocking I/O: Node.js enables the efficient handling of concurrent operations without waiting for tasks to complete.
  • Single-threaded Event Loop: It facilitates high performance by processing tasks without the overhead of multi-threading.
  • Extensive Package Ecosystem: Supported by npm, it offers a vast library of modules simplifying various development tasks.

How does the Node.js file system module work?

The file system (fs) module in Node.js enables developers to interact with files on the system, allowing for file creation, reading, writing, and deletion. It offers both synchronous and asynchronous methods, where asynchronous methods allow other code to continue executing without waiting for file operations to complete, thanks to Node.js’s event-driven nature.

How does event-driven programming work in Node.js?

Node.js employs an event-driven programming model. Through the EventEmitter class, developers can attach functions (event listeners) to specific events. When an event is triggered, the associated function runs, making it possible to create responsive, real-time applications.

What are some advanced topics to learn after Node.js basics?

After learning the basics, consider exploring topics like integrating Node.js with databases (e.g., MySQL or MongoDB), creating modules, handling HTTP requests, managing npm dependencies, and building applications with the MERN or MEAN stacks. Educative offers hands-on projects, such as building REST APIs, Telegram bots, and e-learning websites, for your practice.


Written By:
Christina Kopecky