Skip to main content
Back to module
Back-End Web APIs · Building with Node

Node.js and npm

Reading56mLesson 1 of 3 in this module

Run JavaScript on your computer with Node.js and manage packages, scripts and secrets with npm.

Why it matters

JavaScript started in the browser, but Node.js lets you run it anywhere: on your laptop, on a server, or as a serverless function. It is one of the most common back-end runtimes, so a front-end developer who knows JavaScript can write an API without learning a new language. npm (the Node package manager) comes with Node and gives you access to millions of open-source packages, including the Express framework you will use in the next lesson.

What Node is (and is not)

Node is a JavaScript runtime: the V8 engine from Chrome plus libraries for files, networking and processes. Compared with the browser:

  • There is no document or window. There is process (arguments, environment variables, exit codes), fs (files), http (servers) and more.
  • Node runs on one main thread with an event loop. While it waits for a database or a file, it handles other requests. That is why most Node APIs are asynchronous (callbacks, promises, async/await). Code that blocks the thread, such as a huge synchronous loop, blocks every request.

Installing Node

Install an LTS (long-term support) release, which is the version most companies run. Use the installer from nodejs.org, or a version manager such as nvm (macOS/Linux) or nvm-windows/fnm (Windows) so you can switch versions per project:

node --version   # e.g. v22.x
npm --version

Running a script

Create hello.js:

const name = process.argv[2] ?? "world";
console.log(`Hello, ${name}! Node ${process.version} on ${process.platform}`);

Run it:

node hello.js Ada
# Hello, Ada! Node v22.11.0 on darwin

process.argv holds the command-line arguments: the Node binary, the script path, then yours.

A project with package.json

Every Node project has a package.json describing it. Create a folder and initialise it:

mkdir hello-api && cd hello-api
npm init -y

The generated file is plain JSON. Two fields are worth adding straight away:

{
  "name": "hello-api",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node index.js",
    "dev": "node --watch index.js"
  }
}
  • "type": "module" lets you use import/export (ES modules) instead of require.
  • scripts are shortcuts: npm start runs node index.js, npm run dev restarts on every save.

Installing a package

npm install express

This does three things:

  1. Downloads the package and everything it depends on into node_modules/.
  2. Adds "express": "^5.x.x" under dependencies in package.json.
  3. Writes package-lock.json, which records the exact version of every package installed.

Tools you only need while developing (test runners, linters) go in devDependencies: npm install --save-dev vitest.

The ^ in ^5.1.0 means "any 5.x version from 5.1.0 up". That follows semantic versioning: MAJOR.MINOR.PATCH, where a major bump may break your code. The lock file is what keeps every machine on the same versions, so commit package-lock.json and use npm ci in CI and deployments; it installs exactly what the lock file says.

Environment variables and secrets

Configuration that differs between machines, such as a port, a database URL or an API key, goes in environment variables, not in code:

const port = Number(process.env.PORT ?? 3000);

Locally, many projects keep these in a .env file. Newer Node versions can load one with node --env-file=.env index.js. The .env file holds secrets, so it must never be committed.

What to commit

Create a .gitignore before your first commit:

node_modules/
.env
  • node_modules/ can be rebuilt from the lock file and can hold tens of thousands of files.
  • .env holds secrets. If a secret is ever pushed, deleting the file later is not enough; it is in the history. Rotate (replace) the secret immediately.

A common pattern is to commit a .env.example with the variable names and fake values, so teammates know what to set.

Choosing packages carefully

Every dependency is code you run with full access to your machine and your server. Before you install one, check that it is maintained, widely used, and spelled correctly (attackers publish "typosquat" packages with near-identical names). npm audit reports known vulnerabilities in what you have installed.

Common mistakes

  • Committing node_modules/ or .env.
  • Not committing package-lock.json, so teammates and servers get different versions.
  • Using npm install in CI instead of npm ci.
  • Installing globally (npm install -g) for project tools. Use npx <tool> or a local devDependency.
  • Blocking the event loop with heavy synchronous work in a request handler.

Quick recap

  • Node runs JavaScript outside the browser on a single-threaded event loop.
  • package.json describes the project and its scripts; package-lock.json pins exact versions. Commit both.
  • npm install <pkg> adds a dependency, npm ci reproduces the lock file exactly.
  • Configuration and secrets live in environment variables; .env and node_modules/ go in .gitignore.

Try it: the Do tab walks you through installing Node, creating a project, adding a package and running your first script.

Also in this lesson: