Last updated: 2026-09-14

Working with Third-Party Packages

The previous two topics covered the mechanics of npm — installing packages, understanding package.json. This topic addresses something different: how to actually choose, evaluate, and work responsibly with the millions of packages available on the npm registry. Installing a package is one command. Knowing whether you should is a separate skill, and it is one that matters more as a project grows and depends on more of them.

Every dependency you add to a project is code you did not write, maintained by people you do not control, that your application now relies on to function. That is not a reason to avoid third-party packages — they are central to how productive Node.js development is — but it is a reason to choose them with some care.


Finding Packages

The npm Registry Website

npmjs.com is the primary way to search the registry directly. Each package's page shows its README, version history, weekly download count, dependency count, and a link to its source repository.

Searching from the Command Line

npm search express

This is functional but less informative than browsing the website directly — most developers searching for a package use the website or a general web search rather than this command.


Evaluating a Package Before Installing It

Before adding a dependency to a real project, a few signals are worth checking.

Weekly Downloads

A package's download count, visible on its npm page, is a rough proxy for how widely it is used and trusted. A package with millions of weekly downloads has been exercised by a vast number of real-world use cases — bugs are more likely to have already been found and fixed. A package with a handful of downloads per week may still be perfectly good, but it warrants more scrutiny.

Last Published Date

A package that has not been updated in several years may be abandoned. This is not automatically disqualifying — some packages are simply complete and stable, with nothing left to change — but combined with other warning signs, a long-stale package is worth investigating further before relying on it.

Open Issues and Pull Requests

A package's GitHub repository shows how actively it is maintained. A large number of open issues with no responses, or pull requests that have sat unmerged for a long time, suggest a project that may not be actively maintained, regardless of how recently it was technically published.

Bundle Size

For packages that will ship to the browser — relevant for the frontend half of full-stack work, less so for a pure backend dependency — the package's size affects how much JavaScript users have to download. bundlephobia.com reports the size a given package adds to a bundle, which is a useful check before adding a large dependency for a small piece of functionality.

Number of Dependencies

A package with very few dependencies of its own is generally a lower-risk addition than one that pulls in dozens of nested dependencies, each of which is itself a piece of code your project now indirectly depends on. This is visible on the npm package page and in package-lock.json after installation.

License

The license field on a package's npm page indicates the legal terms under which it can be used. MIT, ISC, and Apache-2.0 are common, permissive licenses well-suited to most commercial and personal projects. Some licenses carry obligations — requiring you to open-source your own code, for example — that matter significantly for commercial projects and are worth checking before depending on a package, particularly for anything central to a paid product.


Reading the README Before Installing

Before running npm install, reading a package's README on its npm page or GitHub repository is worth the few minutes it takes. It typically shows the basic usage, the API surface, and whether the package actually does what you think it does, before it becomes a dependency your code is built around.


A Practical Example — Choosing Between Similar Packages

It is common for multiple packages to solve the same problem. For making HTTP requests from Node.js, for example, both axios and node-fetch (or the native fetch, available since Node.js 18) are widely used options.

axiosNative fetch
Installation requiredYesNo — built into Node.js 18+
Automatic JSON parsingYesNo — requires .json() call
Request/response interceptorsYesNo — requires manual wrapping
Built-in request cancellationYes (via AbortController, also supported by fetch)Yes
Bundle size impact (frontend use)Adds to bundle sizeNone — built in

Neither is universally correct. axios offers a more convenient API with features fetch lacks natively, at the cost of an additional dependency. Native fetch requires no installation and is consistent with browser JavaScript, at the cost of slightly more manual work for things like automatic JSON parsing. The right choice depends on the project's specific needs — this kind of comparison, weighing convenience against dependency footprint, is the evaluation process worth applying to any package decision, not just this one.


Reading Documentation and API Usage

Most well-maintained packages document their API directly in the README, often with the most common usage pattern shown first:

// Example from a typical package README
const axios = require('axios');

axios.get('https://api.example.com/users')
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error(error.message);
  });

For packages with a larger API surface, dedicated documentation sites are common — Express, for example, maintains full documentation separate from its README. Getting comfortable navigating a package's documentation, rather than guessing at its API from memory or from incomplete examples found elsewhere, is a skill that pays off across every package you will ever use.


Updating Dependencies Safely

As covered in npm Basics, npm outdated shows which installed packages have newer versions available. Updating dependencies is necessary — security patches, bug fixes, and new features all arrive through updates — but it should be done deliberately, not blindly.

npm outdated
Package    Current   Wanted   Latest
express    4.17.1    4.18.2   4.18.2
mongoose   6.0.0     6.12.0   7.5.0

The Current column shows what is installed. Wanted shows the highest version satisfying the existing version range in package.json — what npm update would install. Latest shows the newest version published, which may fall outside the current range entirely if a MAJOR version has been released.

Updating from Current to Wanted is generally low-risk, since it stays within the MINOR/PATCH range already considered safe by semantic versioning. Updating to Latest when it represents a MAJOR version bump — as mongoose does in the example above, jumping from 6.x to 7.x — should be treated as a deliberate decision, not an automatic one. MAJOR version updates can include breaking changes, and the package's changelog should be reviewed before upgrading.

npm install mongoose@latest

After any significant dependency update, running the project's test suite (or, at minimum, manually verifying core functionality) before deploying is the responsible practice — an update that looks routine on paper can still introduce a regression in how your specific code uses that package.


Removing Unused Dependencies

Over the life of a project, dependencies accumulate — a package gets installed to try something, the approach changes, and the unused package remains in package.json indefinitely. Periodically reviewing and removing unused dependencies keeps the project's dependency tree smaller, reduces the security surface area covered by npm audit, and makes the codebase easier to reason about.

npm uninstall unused-package

Tools like depcheck can be installed to automatically scan a project and report dependencies that are listed in package.json but never actually imported anywhere in the code:

npx depcheck

A Note on Trust and Supply Chain Risk

Every package installed becomes code that runs as part of your application, with the same level of access your own code has. This is worth taking seriously, particularly for packages handling sensitive operations — authentication, payments, anything touching user data directly.

npm audit, covered in the npm Basics topic, checks installed packages against known vulnerabilities and should be run periodically, particularly before deploying changes to production. Preferring well-established, actively maintained packages with a track record — rather than the newest, least-scrutinised option that happens to solve the same problem — is a reasonable default whenever there is a meaningful difference in the level of trust involved.


Summary

ConsiderationWhat to Check
Popularity and trustWeekly downloads, GitHub stars
Maintenance healthLast published date, open issues, recent commits
Dependency footprintNumber of nested dependencies, bundle size (for frontend packages)
Legal termsLicense type
Documentation qualityREADME clarity, presence of usage examples
Before updatingnpm outdated — review Current vs Wanted vs Latest
MAJOR version updatesReview the changelog before upgrading; test afterward
Securitynpm audit, prefer established and actively maintained packages
HousekeepingPeriodically remove unused dependencies with depcheck or manual review