Tech Handbook Null Yard

Node.js - Practical Handbook

Node.js is a JavaScript runtime outside the browser. When reading a project, focus on package.json, the lockfile, modules, npm scripts, environment configuration and how the process is started in development and production.

For new projects, prefer a supported LTS line instead of tying the project to an arbitrary Current release.

Related topics: JavaScript, APIs and System Integrations, SQL and PostgreSQL for Developers, Docker and Software Testing.

1. What Node.js actually is

Node.js is a JavaScript runtime built on V8 that lets JavaScript run outside the browser, especially for servers, CLI tools and build tooling.

2. Node.js, npm and npx - what is what?

Node.js

The runtime that executes JavaScript.

npm

Package manager and script runner distributed with Node.

npx

Runs package-provided binaries, usually without requiring a permanent global install.

3. Installing Node.js

Use a supported Node release through your distro, NodeSource, nvm/fnm or another approved version manager.

4. Node.js project - most important files

package.json

Project metadata, scripts, dependencies and module settings.

5. The scripts section in package.json

"scripts": {
  "dev": "node --watch src/index.js",
  "test": "node --test"
}

6. package-lock.json

Locks exact dependency versions/resolution for reproducible npm installs.

7. node_modules

Directory containing installed dependencies. It is normally not committed.

8. npm install vs npm ci

npm install

Installs dependencies and may update the lockfile.

npm ci

Requires the lockfile to match package.json and installs a clean reproducible dependency tree.

9. dependencies and devDependencies

Runtime packages belong in dependencies; build/test/lint tooling usually belongs in devDependencies.

10. Installing packages

npm install express
npm install -D eslint

11. Package versioning

Exact version

1.2.3 pins exactly.

Caret

^1.2.3 normally allows compatible minor/patch updates within major 1.

Tilde

~1.2.3 normally allows patch-level updates.

12. Updating packages

npm outdated
npm update

13. JavaScript needed to read Node.js

Variable let

Block-scoped mutable binding.

Constant const

Block-scoped binding that cannot be reassigned.

var

Legacy function-scoped declaration.

14. Data types

Node uses standard JavaScript types: string, number, boolean, null, undefined, object, bigint, symbol.

15. Strings

const name = 'Ada';
const message = `Hello ${name}`;

16. Arrays

const items = [1,2,3];
items.push(4);

17. Objects

const user = { id: 1, name: 'Ada' };

18. Destructuring

const {id, name} = user;
const [first] = items;

19. Spread operator

const copy = {...user};
const all = [...a, ...b];

20. Functions

function add(a,b) { return a+b; }

21. Arrow functions

const add = (a,b) => a+b;

22. Conditions

if (ready) { ... } else { ... }

23. Comparisons

Prefer strict equality === and !== unless coercion is intentionally required.

24. Logical operators

a && b
a || b
!a

25. Optional chaining

user.profile?.email

26. Nullish coalescing

const port = env.PORT ?? 3000;

27. Conditional operator

const label = ok ? 'yes' : 'no';

28. Loops

for (const item of items) { ... }

29. map, filter, find

map

Transforms every item and returns a new array.

filter

Keeps items matching a predicate.

find

Returns the first matching item.

30. Modules

Node supports CommonJS and ES Modules.

31. CommonJS

const fs = require('node:fs');
module.exports = { helper };

32. ES Modules

import fs from 'node:fs';
export function helper() {}

33. import - how to read it

Identify whether the import comes from Node core (node:), an npm package, or a local relative path.

34. Built-in Node.js modules

Recognize node:fs, node:path, node:http, node:url, node:events, node:stream, node:crypto, node:child_process.

35. Working with files

import {readFile} from 'node:fs/promises';
const text = await readFile('file.txt', 'utf8');

36. Asynchrony - key to Node.js

Most I/O is asynchronous so one process can handle many waiting operations without blocking a thread per request.

37. Promise

Represents a future fulfilled or rejected result.

38. async / await

async function load() {
  const data = await readFile('x.txt','utf8');
  return data;
}

39. Error handling

try {
  await work();
} catch (err) {
  console.error(err);
}

40. throw

throw new Error('invalid state');

41. Event loop - enough for now

JavaScript runs on a call stack while libuv coordinates timers and asynchronous I/O callbacks/promises.

42. process

Global object exposing arguments, environment, exit code, signals and process metadata.

43. Environment variables

const port = process.env.PORT ?? '3000';

44. .env file

A common local convention for environment variables. Loading it requires Node's supported env-file option or a library/tool, depending on project/runtime.

45. Running after cloning a project

git clone REPO
cd PROJECT
npm ci
npm test
npm run dev

46. How to find the application entry point

Check package.json main, exports, scripts, framework config and files such as src/index.js, server.js, app.js.

47. How to read a Node.js project

Start with package.json and scripts, then entry point, routes/controllers/services, config and tests.

48. Typical Express architecture

routes

Map HTTP methods/paths to handlers.

controllers

Translate HTTP requests/responses.

services

Business logic.

models

Data models or persistence entities.

middleware

Cross-cutting request processing such as auth/logging/validation.

49. req and res

Express request and response objects.

50. URL parameters

app.get('/users/:id', (req,res) => req.params.id);

51. Query string

const q = req.query.q;

52. Request body

Parsed by body middleware/framework support and should always be validated.

53. HTTP status

res.status(201).json(data);

54. Node backend and frontend

A Node backend can serve APIs, HTML or static files; frontend code still runs in the browser.

55. Does Node.js compile?

Node normally executes JavaScript directly, though projects may transpile/bundle TypeScript or frontend code before production.

56. TypeScript

Adds static type checking and syntax that compiles/transpiles to JavaScript.

57. tsconfig.json

Configures TypeScript compiler behavior.

58. Project build

npm run build executes whatever command the project defines, often TypeScript compilation or bundling.

59. Development vs production

Development favors watch/debug tooling; production favors built artifacts, stable config, supervision and observability.

60. NODE_ENV

Common convention used by libraries/apps to select development/production behavior.

61. Watch mode

node --watch src/index.js

62. Simplest debugging

Start with stack traces, focused logs and reproducible inputs.

63. Node debugger

node --inspect src/index.js

64. debugger

debugger;

Pauses when a debugger is attached.

65. Stack trace

Read the first application frame around the error and follow callers upward.

66. Linter

ESLint is a common static code-quality tool.

67. Formatter

Prettier or project-standard formatting keeps style automatic.

68. Tests

Projects may use Node test runner, Vitest, Jest, Mocha and others.

69. Built-in Node test runner

node --test

70. How to find tests

Look for test, tests, __tests__, .test.js, .spec.js and package scripts.

71. Most important ecosystem tools

Express

Minimal web framework.

Fastify

Fast structured web framework.

NestJS

Opinionated TypeScript backend framework.

Vite

Frontend dev/build tool.

React

UI library.

Vue

UI framework.

Angular

Full frontend framework.

Prisma

ORM/database toolkit.

Sequelize

ORM.

Drizzle

TypeScript SQL ORM/query toolkit.

72. JSON

const text = JSON.stringify(obj);
const obj = JSON.parse(text);

73. npm, yarn, pnpm

npm

Default Node package manager.

yarn

Alternative package manager.

pnpm

Alternative with content-addressable storage and efficient linking.

74. Corepack

Tool for managing supported package-manager versions such as Yarn/pnpm in projects.

75. How to recognize project technology

Express

express dependency/routes.

React

react/react-dom.

Vue

vue dependency and SFCs.

Angular

@angular packages/angular.json.

Vite

vite dependency/vite.config.

Next.js

next dependency/app or pages directory.

NestJS

@nestjs packages and decorators.

76. What npm run build really does

Exactly whatever is defined under the build script in package.json.

77. Production environment

Use explicit Node version, immutable deployment artifact, secrets/config, process supervision, reverse proxy where appropriate and monitoring.

78. Simplest deployment on Debian

Build/test app, copy/pull source or artifact, npm ci, configure env, run under systemd and proxy with nginx.

79. Do not run production from a terminal

An SSH terminal is not a process supervisor. Use systemd, container orchestration or another service manager.

80. systemd

Define a unit with working directory, user, environment and ExecStart.

81. Starting systemd

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp

82. nginx as reverse proxy

Bind Node to localhost/private port and let nginx terminate TLS and expose the public hostname.

83. Application port

Read it from code/config/env and confirm with ss -lntp.

84. PM2

Node-focused process manager. Useful in some stacks, but systemd is often sufficient on a normal Debian server.

85. Deployment with Docker

Package runtime, app and production dependencies into an image; keep state outside the container.

86. Multi-stage Docker build

Use one stage to install/build and a slimmer stage for runtime.

87. .dockerignore

Exclude node_modules, Git, local secrets, logs and build junk from the Docker build context.

88. Deploying a static frontend

Build to dist/build and serve static files from nginx/CDN; Node may not be required at runtime.

89. Typical backend deployment

Reverse proxy → Node service/container → database/external services.

90. Manual deployment after update

git pull
npm ci
npm test
npm run build
sudo systemctl restart myapp

91. Simple deploy script

Automate the same validated steps and fail on errors.

92. CI/CD

CI validates code; CD packages and/or deploys after checks.

93. Basic GitHub Actions

Checkout → setup-node → npm ci → test → build.

94. Logs

Use stdout/stderr with systemd/container logging or structured logging library.

95. Port problems

ss -lntp | grep ':3000'

96. Problem: command not found

Check package script, local node_modules/.bin, PATH and whether dependencies were installed.

97. Problem: Cannot find module

Check dependency install, import path, package exports and case sensitivity.

98. Problem: Node version

Compare node --version, package engines, .nvmrc, .node-version and CI config.

99. engines

package.json field documenting supported Node/package-manager versions.

100. ES Modules problem

Check type: module, file extensions, import syntax and package exports.

101. Problem with .env

Check whether the project actually loads it, filename/path, process environment and working directory.

102. Deployment debugging

Service status → logs → env → process → port → local curl → reverse proxy → firewall/DNS.

103. curl - very important for backends

curl -v http://127.0.0.1:3000/health

104. Security

Validate input, protect secrets, keep dependencies current, use least privilege, secure cookies/headers and avoid unsafe eval/shell execution.

105. npm scripts can do anything

Installing or running packages may execute arbitrary shell commands through lifecycle scripts.

106. Lifecycle scripts

Hooks such as preinstall/postinstall/prepare can run during package operations.

107. Installing without scripts

npm ci --ignore-scripts

Useful for auditing, but some legitimate packages need build scripts.

108. package.json - quick audit

Check scripts, dependencies, engines, type, exports, package manager and suspicious lifecycle commands.

109. What else may exist in a project

Lockfiles, tsconfig, eslint/prettier config, Dockerfile, compose.yaml, framework config, migrations, env examples.

110. docker compose

Defines multi-service local/production stacks such as app + database + cache.

111. Databases

Node commonly talks to PostgreSQL, MySQL/MariaDB, SQLite, MongoDB, Redis and others.

112. Migrations

Versioned schema changes run through ORM/query/migration tools.

113. Prisma

Schema-driven ORM/database toolkit with generated client and migrations.

114. Middleware

Function in request pipeline that can inspect/modify request/response or delegate to next handler.

115. Callback

Function passed for later invocation. Modern code often wraps callbacks with Promises/async APIs.

116. Classes

class Service {
  constructor(repo) { this.repo = repo; }
}

117. this

Depends on call form; arrow functions capture lexical this, normal functions have dynamic receiver binding.

118. Import aliases

Build/runtime config can map aliases such as @/ to project paths.

119. index.js as a barrel

Re-exports items from multiple modules to present one import surface.

120. Reading a function

Identify inputs, outputs, side effects, awaits, thrown errors and dependencies.

121. How to read a larger function

Split it into phases: validation → loading → transformation → side effects → response.

122. How to check where a function comes from

Use editor Go to Definition or search imports/exports.

123. How to find function usage

rg 'functionName' .

124. rg - basics

rg 'pattern' src

125. find

find . -type f -name '*.js'

126. tree

tree -L 2

127. npm ls

npm ls package

128. npm explain

npm explain package

129. npm view

npm view package version

130. Global packages

npm list -g --depth=0

Prefer project-local tools unless a global CLI is intentionally needed.

131. Shebang in CLI tools

#!/usr/bin/env node

132. CLI in Node

Parse process.argv directly or use libraries such as commander/yargs.

133. Streams

Incremental data interfaces for files, HTTP and pipelines; avoid loading huge data entirely into memory.

134. Buffer

Node's byte container for binary data.

135. EventEmitter

Publish/subscribe primitive used throughout Node APIs.

136. HTTP without a framework

import http from 'node:http';
http.createServer((req,res)=>{ res.end('ok'); }).listen(3000);

137. fetch

Modern Node versions provide standards-based fetch.

138. REST API

Resource-oriented HTTP endpoints using methods/status codes/JSON conventions.

139. WebSocket

Persistent bidirectional connection for real-time communication.

140. worker_threads

Threads for CPU-heavy JavaScript work; not normally needed for ordinary I/O.

141. child_process

Runs external programs. Validate arguments and avoid shell injection.

142. Most important security traps

Command injection, path traversal, SSRF, prototype pollution, insecure deserialization patterns, secret leaks and vulnerable dependencies.

143. Sanitization and validation

Validate type/shape/range; sanitize only for the output context where needed.

144. CORS

Browser access-control policy, not authentication.

145. JWT

Signed token format. Validate signature, issuer/audience/expiry and keep signing keys safe.

146. Session

Server-side or store-backed authenticated session usually referenced by a secure cookie.

147. Password hashing

Use dedicated password-hashing algorithms/libraries such as Argon2 or bcrypt, never plain SHA.

148. Semantic versioning

Major.Minor.Patch convention used widely in npm.

149. ESM extensions

Relative ESM imports may require explicit file extensions depending on runtime/config.

150. npm cache

npm cache verify

151. Memory leak and RAM

Watch retained objects, unbounded caches/listeners/timers and long-lived closures. Use heap snapshots/profilers.

152. NODE_OPTIONS

Environment variable for Node runtime options; treat production use carefully.

153. Exit code

0 means success by convention; non-zero means failure.

154. Signals

Servers commonly handle SIGTERM/SIGINT to begin graceful shutdown.

155. Graceful shutdown

Stop accepting new work, close server/database connections, finish bounded in-flight work, then exit.

156. package-lock and repository security

Commit the lockfile for applications and review unexpected dependency-tree changes.

157. Monorepo

One repository containing multiple packages/apps.

158. Workspaces

Package-manager feature for linking/managing multiple local packages.

159. Running npm from repository root

Workspace scripts can target one or many packages depending on package manager.

160. Source maps

Map generated/transpiled code back to original TypeScript/source for debugging.

161. What dist means

Conventional directory for built/transpiled distributable output.

162. public

Common directory for assets copied/served without module processing.

163. static

General name for files served directly rather than generated dynamically.

164. Template engines

Server-side HTML renderers such as EJS, Pug or Handlebars.

165. Next.js

React framework supporting server rendering, routing, server components/API routes and build tooling.

166. SSR

Server-side rendering generates HTML on the server per request/build strategy.

167. SPA

Single-page app updates client-side UI without full page reloads.

168. How to tell whether Node is required in production

If the result is only static files, no. If server-side rendering/API/background jobs run in Node, yes.

169. Order for analyzing an unfamiliar repo

package.json → lockfile → scripts → entry point/framework → env/config → routes/features → tests → deployment.

170. First commands after clone

node --version
npm --version
npm ci
npm test
npm run build

171. Audit without running code

Read package.json scripts/deps, lockfile, install hooks, Docker/CI config and env examples before executing anything.

172. Finding environment variables

rg 'process\.env' .

173. Finding the port

rg 'listen\(|PORT' src .

174. Finding endpoints

rg 'app\.(get|post|put|delete)|router\.' src

175. Finding the database

Look for ORM packages, connection URLs, migrations and config names such as DATABASE_URL.

176. Finding external APIs

Search fetch, axios/http clients, URLs, SDK packages and environment variables.

177. Reading the technology stack from package.json

Dependencies and scripts quickly reveal frameworks, database clients, test runners and build tools.

178. How not to read Node

Do not read node_modules; start from project code and package metadata.

179. Most important file extensions

.js, .mjs, .cjs, .ts, .tsx, .jsx, .json and framework-specific files.

180. JSX

JavaScript syntax extension compiled into element creation/framework calls.

181. Importing CSS

Frontend bundlers/frameworks may treat CSS as a module side effect; Node itself does not natively execute CSS.

182. Dynamic import

const mod = await import('./feature.js');

183. JSON import

Support depends on module system/runtime version; many projects read JSON with fs or import attributes.

184. top-level await

Allowed in ES modules in supported Node versions.

185. main pattern

Keep startup in a small entry point that loads config, creates dependencies and starts services.

186. Dependency injection

Pass dependencies explicitly rather than importing global singletons everywhere.

187. Repository

Persistence/data-access abstraction.

188. Controller

HTTP/input boundary translating request into service call and response.

189. Service

Application/business logic.

190. Config

Validated configuration object derived from environment/files.

191. Feature flags

Runtime or deployment-controlled switches for staged functionality.

192. Request logging

Log method/path/status/duration/request ID, avoiding secrets.

193. Health endpoint

Simple endpoint indicating whether process/dependencies are healthy enough for traffic.

194. Healthcheck in shell

curl -fsS http://127.0.0.1:3000/health

195. npm start in production

Only meaningful if package.json defines a production-appropriate start script.

196. Dev server is not a production server

Watch/HMR tooling is for development; use the framework's documented production build/runtime.

197. Minimal production workflow

Install reproducibly → test → build → deploy artifact → start under supervisor → health check.

198. Rollback

Keep previous artifact/image/release and a documented database-compatible rollback path.

199. npm ci and production dependencies

npm ci --omit=dev

200. Build and deploy - good separation

Build in CI or controlled build stage; deploy immutable output rather than compiling unpredictably on production when possible.

201. Node in Docker - good mental model

Container = Node runtime + app + production dependencies; config/secrets/state arrive from outside.

202. Docker volumes

Use for persistent runtime data only when the application genuinely needs local persistence.

203. Node and SQLite

Fine for small/single-instance workloads; understand file locking, backups and container volume placement.

204. Node as developer tooling

Even static frontend projects may use Node only for npm/Vite/build/test and not in production.

205. Importance of lockfile during deployment

The lockfile ensures the dependency graph tested in CI is the one installed in deployment.

206. Minimal syntax you must recognize

const/let, objects/arrays, destructuring, functions, async/await, import/export, map/filter/find, try/catch.

207. Mental model of an async function

Calling it returns a Promise; await pauses that async function until the awaited promise settles.

208. Mental model of import

Import connects modules through explicit exported bindings.

209. Mental model of middleware

A chain around request handling that can act before/after delegating to the next layer.

210. Mental model of callback

A function value handed to code that calls it later.

211. Mental model of map

One input item becomes one output item; returns a new array.

212. Mental model of filter

Predicate decides which input items remain.

213. Mental model of destructuring

Pattern extracts named/indexed pieces from an object/array.

214. Mental model of spread

Copies/expands iterable/object properties into a new surrounding structure.

215. Checklist: I received an unfamiliar Node repo

Read package.json, identify Node/package manager version, inspect scripts/deps, install with lockfile, run tests/build, find entry/env/port and deployment files.

216. Checklist: deployment on Debian

Node version → service user → artifact/source → npm ci → build → env → systemd → localhost curl → nginx → logs.

217. Checklist: something does not work

Exact error → logs/stack → Node version → env → dependency install → process → port → local curl → proxy/network.

218. Most important Node/npm commands

node --version
npm --version
npm ci
npm run
npm test
npm run build
npm ls
npm explain

219. Most important deployment commands

systemctl status/restart
journalctl -u SERVICE
ss -lntp
curl -v localhost:PORT
nginx -t

220. Most important questions when analyzing a project

What starts it? Which Node version? Which scripts? Which env vars? Which port? Which DB/APIs? How is it built/tested/deployed?

221. Example analysis of a fictional project

package.json says Fastify + Prisma + TypeScript; scripts reveal dev/build/start; Prisma schema reveals DB; src/server.ts is entry point; Dockerfile/systemd reveals deployment.

222. Example deployment of that project

npm ci → tests → npm run build → migrations → restart service → health check → inspect logs.

223. Node.js vs Go - quick mental comparison

Node is dynamic JS with event-loop I/O and huge web ecosystem; Go is statically typed, compiled to a simple binary with built-in concurrency.

224. Node.js vs JavaScript

JavaScript is the language; Node.js is one runtime environment for that language.

225. What you really need to remember

package.json/scripts, lockfile, npm ci, modules, async/await, env vars, logs, process supervision, reverse proxy and reproducible deployment.

226. Cheat sheet - analyze a project in 5 minutes

cat package.json
node --version
npm ci
npm test
npm run build
rg 'process.env|listen\(' src
tree -L 2

227. Cheat sheet - reading syntax

const/let
{} object
[] array
=> function
await Promise
?. optional
?? fallback
... spread/rest
import/export

228. Cheat sheet - deployment

npm ci
npm run build
systemctl restart APP
journalctl -u APP
curl localhost:PORT/health
nginx -t

229. What is worth learning later

Streams/backpressure, profiling, worker threads, advanced ESM/package exports, framework internals, observability and supply-chain security.

230. Final mental model

A Node project is package metadata + JavaScript/TypeScript modules + dependencies + scripts + runtime config. Understand those five and most unfamiliar repositories become manageable.

Official references

  • Node.js documentation: https://nodejs.org/docs/latest/api/
  • Node.js release schedule: https://nodejs.org/en/about/previous-releases
  • npm documentation: https://docs.npmjs.com/