Ctrl + K
JavaScript16 min read

Understanding node_modules

Understand what node_modules contains, how dependencies are installed, how npm resolves packages and why node_modules should usually not be committed to Git.

Published: 2026-09-02

The node_modules directory is where npm and other JavaScript package managers install the dependencies required by a project. When you run npm install, packages declared in package.json are downloaded and placed into node_modules together with the dependencies those packages require.

For many JavaScript developers, node_modules is one of the most familiar directories in a project and one of the least understood. It can contain hundreds or thousands of files, become surprisingly large and sometimes seem to appear or disappear depending on the package manager and installation command being used.

What Is node_modules?

node_modules is a directory used by Node.js projects to store installed JavaScript packages. When a project depends on a package such as React, Express or TypeScript, the package manager normally places the package inside node_modules so that the project can access it.

my-project/
├── package.json
├── package-lock.json
├── node_modules/
│   ├── package-a/
│   ├── package-b/
│   └── package-c/
└── src/

The directory is normally generated rather than written manually. Developers describe dependencies in package.json, and the package manager determines what needs to be installed and creates the corresponding node_modules structure.

Why Does node_modules Exist?

JavaScript applications frequently depend on code written by other developers or organizations. Instead of copying that source code into every project manually, package managers download published packages and install them locally.

  • Store project dependencies locally.
  • Make installed packages available to the application.
  • Store transitive dependencies required by other packages.
  • Allow Node.js tools to resolve imported packages.
  • Keep project dependencies separate from system-wide software.

How node_modules Is Created

The most common way to create node_modules is by installing project dependencies with npm. When npm reads package.json, it determines which dependencies are required, resolves their versions and downloads the necessary packages.

npm install

After the command finishes, the project normally contains a node_modules directory and a lockfile. The exact contents depend on the dependency tree resolved by npm.

package.json
    ↓
npm install
    ↓
Resolve dependencies
    ↓
Download packages
    ↓
Create node_modules
    ↓
Project can import dependencies

What Is Stored Inside node_modules?

node_modules contains installed packages and the files published with those packages. Depending on the package, this can include JavaScript or TypeScript source files, compiled code, type declarations, package metadata, command-line binaries and additional assets.

ContentPurpose
JavaScript filesPackage runtime code
Type declarationsTypeScript type information
package.jsonPackage metadata and dependency information
bin filesCommand-line executables exposed by packages
Supporting filesDocumentation, configuration or package-specific assets

Direct Dependencies and node_modules

Direct dependencies are packages explicitly listed in your project's package.json. For example, if a project declares React as a dependency, React is a direct dependency of that project.

{
  "dependencies": {
    "react": "^19.0.0",
    "axios": "^1.0.0"
  }
}

After installation, the corresponding packages can normally be found under node_modules. However, node_modules can also contain packages that are not listed directly in package.json.

What Are Transitive Dependencies?

A transitive dependency is a package required by another dependency. For example, your application might depend on Package A, while Package A depends on Package B. Your application therefore indirectly depends on Package B.

Your project
    ↓
Package A
    ↓
Package B
    ↓
Package C

This dependency chain explains why node_modules can contain far more packages than are listed in package.json. A project with a small number of direct dependencies can still have a large dependency tree.

⚠️ Do not assume that every package inside node_modules was installed directly by your project. Many packages are transitive dependencies required by other packages.

Why Is node_modules So Large?

node_modules can become very large because modern JavaScript applications often depend on many packages. Each package may have its own dependencies, which can create a large dependency graph.

The number of files can also be much larger than the number of packages. A single package can contain many source files, generated files, type definitions, metadata and other resources.

ReasonEffect
Many dependenciesMore installed packages
Transitive dependenciesDependency tree becomes deeper
Package contentsEach package can contain many files
Multiple versionsDifferent dependency branches may require different versions
Tooling packagesDevelopment dependencies add more files

Why Can node_modules Contain Multiple Versions of a Package?

Different dependencies can require incompatible versions of the same package. A package manager may therefore install more than one version when a single version cannot satisfy all dependency requirements.

Application
├── Package A
│   └── shared-package@1.x
└── Package B
    └── shared-package@2.x

Modern package managers use dependency resolution and deduplication strategies to avoid unnecessary duplicates when possible. However, multiple versions can still be necessary when dependency requirements do not overlap.

How Node.js Finds Packages

When JavaScript code imports a package, Node.js uses its module resolution rules to determine where the requested package can be found. For a package import such as an installed library, Node.js searches appropriate node_modules locations relative to the importing file and its parent directories.

import express from "express";

The application does not normally need to specify the full path to node_modules. The module resolution system allows package names to be resolved through the project's dependency directories.

The node_modules/.bin Directory

Many npm packages expose command-line programs through a bin field in their package.json. When such packages are installed, npm creates executable links or files in node_modules/.bin.

node_modules/
└── .bin/
    ├── tsc
    ├── vite
    └── eslint

These commands can then be used by package.json scripts without requiring a global installation. For example, a project can run a locally installed compiler or linter through an npm script.

{
  "scripts": {
    "build": "tsc",
    "lint": "eslint ."
  }
}
💡 Using project-local command-line tools from node_modules helps keep development environments consistent because the project controls which tool version is executed.

node_modules and devDependencies

Both dependencies and devDependencies can be installed into node_modules during a normal development installation. The difference is not that one category lives in node_modules and the other does not, but how those packages are intended to be used and whether production-only installation should include them.

SectionTypical Purpose
dependenciesPackages required by the application
devDependenciesPackages primarily needed for development, testing or building

Tools such as TypeScript, ESLint, testing frameworks and bundlers are commonly development dependencies. A production environment may install only production dependencies when the application does not need those development tools at runtime.

node_modules and package.json

package.json describes the dependencies a project requests, while node_modules contains the packages actually installed in the current environment. The two are related but serve different purposes.

ComponentRole
package.jsonDeclares project dependencies and scripts
package-lock.jsonRecords the resolved dependency tree
node_modulesContains installed package files

This distinction is important when working with Git. package.json and package-lock.json are project files that should generally be committed, while node_modules is generated installation output and is normally excluded.

Should node_modules Be Committed to Git?

For typical Node.js projects, node_modules should not be committed to Git. It can be regenerated from package.json and the lockfile, so storing the entire directory in a repository adds unnecessary size and noise.

node_modules/

The node_modules directory is therefore commonly included in .gitignore. Other developers can clone the repository and run npm install or npm ci to recreate the directory locally.

⚠️ Do not add node_modules to a Git repository just because the application needs it to run. Dependencies should normally be installed from the project's package files instead of being stored as generated repository content.

Why node_modules Should Usually Be Ignored

  • It can contain thousands of files.
  • It can make Git repositories unnecessarily large.
  • Dependencies can be regenerated from package files.
  • Generated files create noisy Git changes.
  • Different operating systems can require different installed artifacts.
  • Package updates would create huge repository diffs.

How to Recreate node_modules

If node_modules is deleted, the directory can normally be recreated by installing the project's dependencies. When a package-lock.json file is available, npm ci is commonly used when an exact clean installation based on the lockfile is desired.

rm -rf node_modules
npm ci

On Windows, the directory can be deleted using File Explorer or an appropriate terminal command. The important point is that node_modules is disposable installation output and can be recreated from the project's dependency definitions.

npm install vs npm ci for node_modules

npm install and npm ci both install dependencies, but their behavior and intended use cases differ. npm install can update package-lock.json when dependency requirements change, while npm ci is intended for clean installations based on an existing lockfile.

Commandnode_modules BehaviorTypical Use
npm installInstalls dependencies and may update the lockfileDevelopment
npm ciRemoves existing node_modules and performs a clean lockfile installationCI/CD and reproducible builds
💡 If you want to completely recreate the installed dependency tree from a committed package-lock.json, npm ci is usually the more appropriate command than npm install.

Can You Delete node_modules?

Yes. In most projects, deleting node_modules is safe because it contains installed dependencies rather than the project's primary source code. The directory can be recreated by running the package manager again.

Developers commonly remove node_modules when troubleshooting installation problems, switching dependency states or cleaning a project before reinstalling packages. However, deleting it does not fix every dependency problem automatically.

When Should You Delete node_modules?

  • After a corrupted or incomplete installation.
  • When dependency resolution behaves unexpectedly.
  • After major dependency changes when a clean installation is useful.
  • When switching between significantly different dependency states.
  • When troubleshooting environment-specific installation issues.
  • Before performing a completely clean dependency installation.

Deleting node_modules Is Not Always the Best First Step

Although reinstalling dependencies is a common troubleshooting technique, repeatedly deleting node_modules can hide the real cause of a problem. Dependency conflicts, incompatible Node.js versions, incorrect package requirements or broken build configuration may remain after reinstalling.

Before deleting everything, check the error message, package.json, package-lock.json, Node.js version and package manager version. A clean installation is useful when the installed dependency state is suspected to be the problem, but it should not replace diagnosing the underlying issue.

node_modules and Operating Systems

Some npm packages include native components that are compiled or downloaded specifically for an operating system, CPU architecture or Node.js runtime. This is another reason why node_modules should generally not be copied between unrelated environments or committed to Git.

A node_modules directory created on one machine may not be suitable for another machine with a different operating system, architecture or runtime environment. Reinstalling dependencies in the target environment is usually safer.

Why Copying node_modules Can Cause Problems

Copying node_modules from another project or computer can produce difficult-to-diagnose problems. Packages may have been installed with different versions of Node.js, different operating-system requirements or a different dependency tree.

⚠️ If a project behaves differently after copying node_modules from another machine, perform a clean installation using the project's package files and lockfile before investigating further.

node_modules and Docker

Docker-based applications require some additional consideration because node_modules may exist both on the host machine and inside the container. Installing dependencies inside the container can ensure that packages are compatible with the container's operating system and runtime.

FROM node:22

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .

CMD ["npm", "start"]

The exact Docker setup depends on the application, but the general principle is to install dependencies in the environment where they will run. This is especially important for packages containing native binaries.

node_modules and Disk Space

Because node_modules can contain many packages and files, it can consume significant disk space. This is normal for projects with large dependency trees, but old project directories can leave many unused node_modules folders on a development machine.

  • Check old projects for unused node_modules directories.
  • Delete generated dependencies when a project is no longer needed locally.
  • Avoid storing node_modules in backups unnecessarily.
  • Use package files to recreate dependencies instead of keeping duplicate copies.

node_modules and Monorepos

Monorepos can have more complex dependency layouts because multiple packages or applications share a single repository. Depending on the package manager and workspace configuration, dependencies may be installed in different locations and may be shared or linked between projects.

npm workspaces, Yarn and pnpm can use different strategies for organizing dependencies. As a result, the exact node_modules structure should not be assumed to be identical across package managers.

node_modules with npm Workspaces

npm supports workspaces for managing multiple packages inside a single repository. A workspace project can have dependencies belonging to individual packages while the package manager manages the overall dependency installation.

{
  "workspaces": [
    "packages/*"
  ]
}

The resulting installation layout depends on the workspace dependency graph. Packages that can be shared may be placed in locations that allow multiple workspaces to use them.

node_modules and pnpm

pnpm uses a different dependency storage and linking strategy from traditional npm installations. It uses a content-addressable store and creates links into project node_modules directories. This can reduce duplicated package data across projects.

The visible node_modules directory therefore does not necessarily mean that every package is stored as a completely independent physical copy inside the project. Package manager implementation details can significantly affect how dependencies are represented on disk.

node_modules and Yarn

Yarn can also manage dependencies differently depending on its version and configuration. Traditional Yarn installations commonly use node_modules, while modern Yarn supports Plug'n'Play, which can operate without a conventional node_modules directory.

This is an important reminder that node_modules is common in JavaScript projects but is not an absolute requirement of every JavaScript package management strategy.

Common node_modules Problems

ProblemPossible Cause
Module not foundDependency is missing or cannot be resolved
Unexpected package versionDependency tree or lockfile differs
Native module errorPackage was built for another environment
Very large directoryLarge dependency tree or multiple projects
Installation failureNetwork, package, runtime or dependency issue

Module Not Found Errors

Errors such as Cannot find module usually indicate that Node.js or the build system cannot resolve a required package or file. The cause may be a missing dependency, an incomplete installation, an incorrect import path or a dependency that was installed only in another environment.

Error: Cannot find module "example-package"

Before reinstalling everything, verify that the package is declared in the correct dependency section and that the expected package actually exists in the installed dependency tree.

Best Practices for Managing node_modules

  • Do not commit node_modules to Git.
  • Keep package.json and the lockfile in version control.
  • Use a consistent package manager across the project.
  • Use npm ci for clean CI installations.
  • Reinstall dependencies in the target environment instead of copying node_modules.
  • Keep Node.js versions consistent between development and deployment.
  • Delete old unused node_modules directories when disk space is needed.
  • Investigate dependency errors instead of repeatedly reinstalling without checking the cause.

Frequently Asked Questions

What is node_modules?

node_modules is the directory where npm and other JavaScript package managers store installed project dependencies and their transitive dependencies.

Should node_modules be committed to Git?

Usually no. node_modules is generated from package.json and the lockfile, so committing it can make repositories unnecessarily large and difficult to maintain.

Can I delete node_modules?

Yes. In most projects, it is safe to delete node_modules because the directory can be recreated by installing the project's dependencies again.

Why is node_modules so large?

It contains direct and transitive dependencies, and each package can contain many files. Large JavaScript projects can therefore produce very large node_modules directories.

Why are there packages in node_modules that are not in package.json?

Those packages are often transitive dependencies required by packages that your project depends on directly.

Can I copy node_modules to another computer?

It is generally better to reinstall dependencies on the target computer. Native packages and environment-specific files may not work correctly when copied between different systems.

What is node_modules/.bin?

node_modules/.bin contains executable links or files created for packages that expose command-line tools through their package configuration.

Does every JavaScript project need node_modules?

No. Many projects use it, but package managers such as modern Yarn can use alternative strategies, including Plug'n'Play, that do not require a traditional node_modules directory.

Helpful JavaScript Tools

An npm Dependency Checker helps inspect project dependencies, a Package-lock Inspector analyzes package-lock.json and resolved dependency information, a Package.json Validator checks package.json structure, a Package.json Formatter improves package.json readability, and a Semantic Version Calculator helps compare and calculate semantic package versions.

Conclusion

node_modules is the local installation directory used by many JavaScript package managers to store project dependencies. It can contain direct dependencies, transitive dependencies, command-line tools, type definitions and other package files required by an application or its development workflow.

The directory is generated and disposable, which is why it should normally be excluded from Git and recreated from package.json and the project's lockfile. Understanding how node_modules relates to package.json, package-lock.json, dependency resolution, CI/CD and different package managers makes JavaScript projects easier to maintain and troubleshoot.

Found an issue?

Found an error, outdated information, or something missing from this article? Let me know through the Contact page.

Your feedback helps improve our articles and keep them accurate and useful.