npm 01 ๐ What is npm and Node Modules
npm is the package manager for the Node JavaScript platform. Its job is to put modules in place so that Node.js can find them, and to manage the dependency conflicts that arise when different packages require different versions of the same library . The name originally stood for “Node Package Manager,” and it refers to three distinct things at once: the command-line tool you run in a terminal, the public registry at registry.npmjs.org where packages are published, and the website that lets you browse and manage them .
The package manager solves a problem that becomes obvious the moment a project needs more than one library. A Node.js application might depend on a web framework, which depends on a router, which depends on a utility library, which depends on another utility library. Installing all of these by hand, in the correct versions, in the correct locations, is not practical. npm reads the project’s package.json file, resolves the full dependency tree, downloads every package, and places them in a node_modules directory where Node.js’s module resolution algorithm can find them . The result is a project that can be cloned, run with npm install, and behave identically on any machine.
Key point: npm is three things in one: a CLI for installing and managing packages, a public registry of JavaScript software, and a website for discovery. It installs packages into a node_modules directory by default, and it records the project’s direct dependencies in package.json and the full dependency tree in package-lock.json.
Why npm and node_modules exist
The dependency problem. A Node.js program that uses only the built-in modules is self-contained. The moment it needs a third-party libraryโa web framework, a database driver, a testing toolโit must obtain that library from somewhere and place it where Node.js can find it. npm is that “somewhere” and that “placement mechanism.” The npm install command reads the project’s declared dependencies, fetches them from the registry, and writes them into node_modules so that require('express') resolves to the installed package .
The version problem. Different packages often depend on different versions of the same library. Package A might require version 1.x of a utility, and package B might require version 2.x. A flat directory of packages cannot hold both versions at the same path. npm solves this with a nested node_modules structure: if a conflict exists, the conflicting version is installed inside the dependent package’s own node_modules folder, and Node.js’s module resolution walks up the directory tree until it finds the closest matching version . This is why node_modules can contain the same package at multiple paths, each with a different version.
The reproducibility problem. A package.json file declares the dependencies a project needs, often with version ranges like ^4.18.0. A range is not a specific version. On a fresh install months later, the range might resolve to a newer version that introduces a breaking change. The package-lock.json file solves this: it records the exact version and resolved location of every package in the tree, and npm install uses it to recreate the identical tree on every machine . This is why the lockfile is committed to version control and node_modules is not.
The size problem. node_modules is famously large because it contains not just the direct dependencies but every transitive dependency, recursively. A project with a dozen direct dependencies can easily have hundreds of packages in node_modules . The folder is not meant to be edited or committed. It is a build artifact, regenerated by npm install from the manifests. The .gitignore entry for node_modules is the standard practice because the lockfile is the source of truth, not the installed files .
a. The three components of npm
The CLI is the component most developers interact with. It is a command-line tool that runs in a terminal and exposes commands like install, publish, search, ls, and update . The CLI reads the project’s package.json, communicates with the registry, and writes to node_modules. It is installed automatically when Node.js is installed, and its version is shown with npm -v .
The registry is a large public database of JavaScript packages and their metadata. By default, npm uses the public registry at https://registry.npmjs.org . The registry stores the package tarballs and the metadata that describes them: the name, version, dependencies, and other fields. You can configure npm to use a different registry, including a private one, by changing the registry configuration option .
The website is the discovery and management interface. It lets you browse packages, read their documentation, and manage your account and organizations . The website and the registry are related but distinct: the website is for humans, and the registry is for the CLI. A package can exist in the registry without being prominently featured on the website, and the website can show information about a package that the CLI does not use directly.
b. Local versus global installation
npm has two modes of operation, and the distinction determines where a package is placed and what it can be used for.
Local mode is the default. Packages are installed into the node_modules directory of the current project, and their executables are linked into ./node_modules/.bin . A locally installed package is available to require() calls within the project and to the scripts defined in the project’s package.json. This is the correct mode for any library that the application’s code imports.
Global mode is activated with the -g or --global flag. Packages are installed into the Node.js installation prefixโtypically /usr/local/lib/node_modules on Unix systemsโand their executables are linked into the prefix’s bin directory . A globally installed package is available as a command-line tool from any directory, but it is not available to require() calls in a project unless the project also installs it locally. The guidance is to install locally if the package is going to be require()d, and globally if it is going to be run from the command line .
| Mode | Location | Executables | Use Case |
|---|---|---|---|
| Local (default) | ./node_modules | ./node_modules/.bin | Libraries imported by code |
Global (-g) | {prefix}/lib/node_modules | {prefix}/bin | CLI tools run from anywhere |
The npm link command bridges the two modes for development. It creates a symbolic link from the global node_modules to the local package, so that a CLI tool under development can be run from anywhere without being published or reinstalled .
c. package.json and node_modules
The package.json file is the manifest. It contains the project’s metadata (name, version, description), its scripts (commands run with npm run), and its dependencies (the packages the project needs). It is the file that npm reads when you run npm install, and it is the file that you edit when you want to add or remove a dependency .
The node_modules directory is the installed output. When you run npm install, npm reads package.json, resolves the dependency tree, downloads the packages, and writes them into node_modules . The directory is not part of the source code. It is a cache and a build artifact, and it is regenerated from the manifest and the lockfile.
// A minimal package.json
{
"name": "my-project",
"version": "1.0.0",
"description": "A sample project",
"main": "index.js",
"scripts": {
// The test command, run with npm test
"test": "node test.js"
},
"dependencies": {
// The runtime dependency and its version range
"express": "^4.18.0"
},
"devDependencies": {
// The development-only dependency
"jest": "^29.0.0"
}
}
The dependencies field lists packages that the application needs at runtime. The devDependencies field lists packages that are only needed during development and testing, and they are skipped when npm install --omit=dev is used in a production build . The node_modules directory contains both sets after a normal npm install, which is why the production build uses the --omit=dev flag to exclude the development packages.
Complete Example Session
The following session creates a project, installs a dependency, and inspects the result.
# ============================================
# PART 1: CREATE THE PROJECT
# ============================================
# Create a directory and enter it
mkdir my-project && cd my-project
# Initialize a package.json with default values
# The -y flag skips the interactive prompts
npm init -y
# The package.json is created with the default fields
cat package.json
# ============================================
# PART 2: INSTALL A DEPENDENCY
# ============================================
# Install express locally
# npm fetches the package and its dependencies
# It writes the package to node_modules
npm install express
# The package.json now lists express in dependencies
grep express package.json
# The package-lock.json is created with the exact tree
ls package-lock.json
# ============================================
# PART 3: INSPECT THE RESULT
# ============================================
# The node_modules directory contains express and its dependencies
ls node_modules | head
# The express package is available to require()
node -e "const e = require('express'); console.log(typeof e)"
# ============================================
# PART 4: THE GLOBAL VS LOCAL DISTINCTION
# ============================================
# Install a CLI tool globally
npm install -g http-server
# The tool is available from any directory
which http-server
# The tool is not available to require() in the project
# because it was installed globally, not locally
The four parts cover the project creation, the dependency installation, the inspection of node_modules, and the global versus local distinction. What the session demonstrates is that npm install is the command that populates node_modules, and the package.json and package-lock.json are the files that make the installation reproducible.
Quick Reference
npm Components
| Component | Purpose |
|---|---|
| CLI | Install, publish, search, manage |
| Registry | Public database of packages |
| Website | Browse, discover, manage account |
Installation Modes
| Mode | Flag | Location |
|---|---|---|
| Local | (default) | ./node_modules |
| Global | -g | {prefix}/lib/node_modules |
Key Files
| File | Purpose |
|---|---|
package.json | Manifest with metadata and dependencies |
package-lock.json | Exact dependency tree for reproducibility |
node_modules | Installed packages (do not commit) |
Dependency Types
| Field | Purpose |
|---|---|
dependencies | Runtime packages |
devDependencies | Development-only packages |
Best Practices
โ Do This:
# Use local install for libraries
npm install express
# Use global install for CLI tools
npm install -g http-server
# Commit the lockfile
git add package-lock.json
# Ignore node_modules
echo "node_modules" >> .gitignore
โ Don’t Do This:
# Commit node_modules
git add node_modules # huge and unnecessary
# Install a library globally
npm install -g express # not available to require()
# Edit the lockfile by hand
vim package-lock.json # regenerated by npm
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
require fails for a global package | Global packages are not in the project tree | Install locally |
node_modules is huge | Transitive dependencies | Normal; do not commit |
| Install differs between machines | No lockfile | Commit package-lock.json |
| Permission errors on global install | Prefix owned by root | Use a version manager |
Real-World Examples
1. Install a dependency
npm install express
2. Install a dev dependency
npm install --save-dev jest
3. Install a CLI tool globally
npm install -g http-server
4. Initialize a project
npm init -y
5. List installed packages
npm ls
6. Search the registry
npm search express
7. Publish a package
npm publish
8. Run a script
npm run test
9. Link a local package
npm link
10. Check npm version
npm -v
Visual
The npm Workflow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ package.json (dependencies) โ
โ โ โ
โ โผ โ
โ npm install โ
โ โ โ
โ โผ โ
โ Registry (registry.npmjs.org) โ
โ โ โ
โ โผ โ
โ node_modules (installed tree) โ
โ โ โ
โ โผ โ
โ require('express') works โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Local vs Global
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ LOCAL (default) โ
โ โ ./node_modules โ
โ โ require() works โ
โ โ ./node_modules/.bin for executables โ
โ โ
โ GLOBAL (-g) โ
โ โ {prefix}/lib/node_modules โ
โ โ require() does NOT work โ
โ โ {prefix}/bin for executables โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Three Components
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CLI Registry Website โ
โ โโโโ โโโโโโโโ โโโโโโโ โ
โ install packages browse โ
โ publish metadata manage โ
โ search tarballs discover โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| npm | Package manager for Node.js |
| Components | CLI, registry, website |
| Default registry | registry.npmjs.org |
| Local install | ./node_modules |
| Global install | {prefix}/lib/node_modules |
| Manifest | package.json |
| Lockfile | package-lock.json |
| Installed tree | node_modules |
| Lockfile in VCS | Yes |
node_modules in VCS | No |
Key takeaways:
- npm is three things in one. The CLI installs and manages packages, the registry stores them, and the website is for discovery and account management .
- Local mode is the default. Packages go into
./node_modules, and they are available torequire()calls in the project. Global mode is for CLI tools that need to be run from anywhere . package.jsondeclares dependencies,package-lock.jsonrecords the exact tree. The lockfile is what makes the install reproducible across machines .node_modulesis a build artifact. It contains every transitive dependency, it is large, and it is not meant to be committed to version control .- The registry is the source of packages. By default, npm uses the public registry, but it can be configured to use a private one .
Remember: npm is the tool that turns a list of dependencies in package.json into a working node_modules directory. The CLI is the interface, the registry is the source, and the lockfile is the guarantee of reproducibility. Install locally for libraries, globally for CLI tools, commit the lockfile, and ignore node_modules. That is the entire workflow.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!