Node: JavaScript Outside the Browser

At its simplest, Node.js (or just “Node”) is JavaScript that runs on a server instead of in a browser. That may sound like a minor distinction, but it changes what the language can do and how you work with it.

The key enabler is V8, Chromium’s JavaScript engine. V8 is the same interpreter that powers JavaScript in Chrome, but it’s not tied to the browser. It can run standalone on a machine, which is exactly what Node uses to execute JavaScript as a server-side language.

Because of this arrangement, Node and browser-based JavaScript are related but not identical. They share the same core language and syntax, but each environment exposes different capabilities:

  • Browser JavaScript has access to the DOM, window, and other browser-specific APIs for manipulating pages and handling user interactions.
  • Node has access to the file system, network sockets, and process management—things a browser would never allow for security reasons.

When you write JavaScript for the browser, you can’t just drop the same code into Node and expect it to work unchanged, and vice versa. The underlying language is the same, but the available features and constraints are quite different.

What npm Actually Is

While Node is the runtime, npm is something else entirely. npm stands for Node Package Manager—even if the official npm website has been known to display jokes like “Ninja Pumpkin Mutants” in its header. The name itself reveals the two-part structure at the heart of npm:

  • Node, the JavaScript runtime that executes your code.
  • Package Manager, the tool that helps you find, install, and manage third-party libraries and tools for your project.

These two pieces are distinct. You don’t need to know Node to use npm, and you don’t need a package manager to write Node code—though in practice they’re almost always used together.

Understanding what Node is and what it does for you is one of the most important steps in making sense of modern web development, so it’s worth taking the time to get comfortable with it.

JavaScript’s Escape from the Browser

Most developers first meet JavaScript as a browser language, sitting alongside HTML and CSS. Tools like TypeScript, Babel, and Sass may transform code into different shapes, but the end result has always been the same: vanilla code meant to run inside a browser.

That limitation no longer exists. JavaScript can run outside the browser entirely, and that's what Node is: JavaScript as a server-side language. When talking about it, it helps to distinguish between “browser-based” JavaScript and what’s sometimes called “Node JavaScript.” The syntax is the same, but the environment is completely different.

From Client Side to Server Side

Client-side languages like HTML, CSS, and JavaScript run in the browser. Server-side languages—PHP, Ruby, Python, and others—run on a server and typically have much broader access to system resources. If the concept of server-side languages is unfamiliar, it’s worth reading up on the basics before continuing.

The relevance here dates back to around 2009, when a group of developers became particularly enamored with JavaScript’s speed, especially compared to the dominant server-side languages of the era. They wanted to use JavaScript everywhere, not just in the browser. The most prominent figure in this movement was Ryan Dahl, who is credited with inventing Node (and later Deno, an anagram of Node).

What Makes Node Possible

Node is essentially JavaScript running as a server-side language outside the browser. The key to making that work lies in the JavaScript engine. Each browser contains its own engine—the component that actually executes JavaScript, separate from the parts handling HTML and CSS.

The engine in Chromium-based browsers is called V8, named after a type of car engine, not the vegetable drink. V8 has become the most popular JavaScript engine, largely thanks to Chrome’s ubiquity rather than any major technical distinction. Thanks to ECMAScript standardization over the last fifteen years, there aren’t significant differences between major browser engines anymore. Firefox's engine, for example, is called SpiderMonkey.

The crucial insight is that a JavaScript engine can be extracted from a browser and run independently, much like pulling a car stereo and repurposing it for a home system. V8 works perfectly fine as a standalone unit in any environment, which is exactly what makes Node possible.

The result is that JavaScript can now run anywhere—not just in browsers. This means front-end developers can work in a server-side language without learning an entirely new syntax.

Not Quite the Same JavaScript

While Node and browser-based JavaScript share core language and syntax, they are alike and quite different at the same time. Browser staples like window, document, and alert don't exist in a Node environment. There's no window when the language runs on its own. New Node developers are often surprised to learn that fetch is a browser API, not core JavaScript.

Some familiar tools remain, though. console.log is still your best friend. Node also brings environment-specific features the browser lacks, such as the process object, which provides details about currently running processes.

A good analogy is the relationship between an upright bass and an electric bass guitar. Both are tuned the same and play the same notes; if you know one, you can learn the other more easily. But they play very differently, and the jobs people do with them rarely look the same.

Node has evolved in its own direction out of necessity. Its import syntax differed from browser JavaScript for years, and only now are the two beginning to converge. Node has also enjoyed the advantage of moving faster than browsers when adopting new features. As a result, Node JavaScript and browser-based JavaScript have become more like cousins than clones. Each can do some things the other can't.

Trying Out Node

Like most server-side languages, Node must be installed before it can be used. It's commonly installed together with npm, since the package manager needs Node, and Node becomes more useful with a package manager.

Keep in mind that you don't need to know anything about Node to use npm. The following example is helpful context but entirely optional for learning npm.

To experiment, create a test.js file with some simple JavaScript that logs content to the console:

console.log('Look, ma, Node hands!')

const oneThroughFive = [1, 2, 3, 4, 5]

oneThroughFive.forEach(number => {
  console.log(number)
})

Save the file, open a terminal, navigate to the file's location with cd, and run node test.js. You should see output similar to this:

Look, ma, Node hands!
1
2
3
4
5

You can also run node by itself, without a filename, to open an interactive terminal where you can execute arbitrary Node JavaScript. If you've used the console in browser DevTools, this works the same way, just on the command line.

A screenshot of an open terminal window showing Node version 17.0.1 running and the output from the previous example under it.

What Comes Next

Node is capable of everything a server-side language can do: reading and writing files, accessing system-level APIs, sending email, responding to requests, running scheduled tasks, and much more. The possibilities have made Node a natural fit for powering server-side applications just as Ruby and PHP did before it.

This also created a need for a way to manage all the Node-based packages that developers use. Node is how those packages run, but installing, updating, and removing them requires a package manager—and that's where npm comes in. The last two letters of npm's abbreviation, package manager, describe exactly what it does. Those packages are essentially tools and scripts written in Node JavaScript, and npm exists to manage them. That's the topic we'll dive into next.