- Lab
- Core Tech

Guided: Package Management in JavaScript
This hands-on lab teaches you npm and pnpm through real-world scenarios that every developer faces. You’ll learn to set up projects, resolve dependency conflicts, troubleshoot common issues, and choose between package managers. Experience the problems that break builds daily: peer dependency warnings, lock file conflicts, cache corruption, and security vulnerabilities. By the end, you’ll confidently manage dependencies and migrate npm/yarn projects to use pnpm.

Path Info
Table of Contents
-
Challenge
Introduction to JS Package Management
JavaScript projects could depend on third-party code — utility libraries, frameworks, tooling, etc. Managing all of these manually is inefficient and error-prone. That’s where package managers come in.
Package managers let you:
- Install libraries/packages from public registries like npm.
- Track version constraints and dependencies.
- Share your own code with others.
Think of them as your app’s supply chain.
There are various package managers for JavaScript projects. The most popular is npm, but others like pnpm, Yarn, and Bun are gaining traction for their performance and features.
Package managers can also help you with scaffolding new project. Let's start the lesson by showing you how to create a new JavaScript project using npm. A
package.json
was created when you initialized the project. Let’s break it down:-
name
: This is the project’s name, by default it uses the name of the working directory. -
version
: The version of the app. Typically follows semantic versioning style. If you're building a private/internal app, this field is not important and can be removed. -
scripts
: Contains scripts and their related commands. For example"start": "node index.js"
adds a script that starts the Node.js app.
There are other important fields that were not added. They are:
-
dependencies
: contains the list of packages which are required to run the application in production. -
devDependencies
: contains the list of packages which are required to run the application during development or build process.
-
Challenge
Working with npm
Most projects need dependencies for various functions. This step is going to show you how to add dependency to your projects. The
prompts
project was added as a runtime dependency to the project. Next, you'll add adevDependency
to the project. After adding those dependency, you will notice the following values have been added to thepackage.json
file:"dependencies": { "prompts: "^2.4.2" }, "devDependencies": { "prettier": "^3.5.3" }
That is how you can tell what kind of dependencies are in a project. ## Lock File Mismatch
Every project has a lock file,
package-lock.json
when using npm. This is used to keep the version consistent across systems.A lock file mismatch happens when
package-lock.json
was manually tampered, whereby the version in the lock file andpackage.json
are different. This can cause serious bugs in production system.To avoid such problems, you should use the
npm ci
command to install dependecies in your CI/CD pipeline. -
Challenge
Peer Dependency Hell
Peer dependencies are packages that a library expect the host application to provide, rather than bundling them directly. This prevent duplicate installations of the same library, or multiple versions of the same library.
They are listed under
peerDependencies
field inpackage.json
. Using peer dependency is very common with UI libraries like React.Peer Dependency Hell
Peer dependency hell occurs when a peer dependency version requirements conflict between packages or what's installed in the host application. There by making installation impossible or leading to runtime bugs if undetected.
I have set up an example with a peer dependency mismatch. The project has the following dependency
"dependencies": { "react": "^16.14.0", "react-router-dom": "^7.6.2" }
How do you know detect the problem? The command exits with an error describing the issue. Somewhere in the error log it says
invalid: ">=18" from node_modules/react-router-dom
This means that the minimum
react
version we should use is18
.The solution here would be to install that version using
npm add react@18
. -
Challenge
Exploring pnpm
pnpm is a different package manager known for being faster than npm, with efficient disk-space management. It uses a unique approach involving hard links and content-addressable storage. This leads to significant benefits, such as:
- Disk Space Efficiency: Dramatically reduces the disk space consumed by
node_modules
because packages are stored only once. - Faster Installs: Subsequent installs are often much quicker as packages are frequently already in the global store.
- Stricter Dependency Resolution: Its linking mechanism creates a "flat"
node_modules
structure where packages can only access explicitly defined dependencies, preventing accidental access to hoisted dependencies and leading to more reliable builds.
You're going to create a project using pnpm. It'll be similar to what you did in the previous steps After the project is set up, and pakcages installed, you should notice the lock file as
pnpm-lock.yaml
. This is pnpm's way of dealing with lock files. The lock file contains information about thelockfileVersion
as well as other pnpm related data.Understanding pnpm's Disk Space Magic
Unlike some other package managers, pnpm doesn't duplicate packages for every project. Instead, it keeps a single global store and links files into each project using hard links. That helps with multiple projects using the same dependency only store it once, which further leads to faster package installs.
pnpm’s Strict Approach to Dependencies
pnpm enforces strict dependency boundaries. It uses a non-flat
node_modules
, therefore your code has no access to packages not listed in yourpackage.json
.For example, the
prompts
package you installed in the previous step has a dependency namedkleur
. Although that dependency was installed alongsideprompts
, you won't be able to usekleur
directly without installing it. That means, the following code won't work:const { bold, green } = require("kleur"); console.log(bold().red("this is a bold red message")); console.log(bold().italic("this is a bold italicized message"));
Meanwhile, if you had used npm, that would work just fine.
Follow the instructions below to verify the
node_modules
tree structure difference between npm and pnpm:- Open and view the file tree for
workspace/step-02/node_modules
. You should see 4 modules, although you only installed prettier and prompts. - Do the same for the directory in
step-04/js-pnpm-lab/node_modules
. You should only seeprompts
as a module directory. Now try to run the code snippet from the previous section, which should show you an error message because kleur is not explicitly installed.
Afterwards, you'll fix it by installing
kleur
as a dependency.The code inside the project located in
step-04/js-pnpm-lab
has been prepared for you. The re-run should successfully execute the code, with the following message printed in the Terminal:this is a bold red message this is a bold italicized message
- Disk Space Efficiency: Dramatically reduces the disk space consumed by
-
Challenge
Security & Supply Chain Attack
JavaScript applications face significant security risks due to vulnerabilities in dependencies and supply chain attacks. A notable example was the compromise of the
ua-parser-js
package in 2021, which affected millions of downloads and injected cryptocurrency miners into applications.Supply chain attacks target the dependency ecosystem by exploiting the trust developers place in third-party packages. These attacks can introduce malicious code that steals data, creates backdoors, or compromises entire systems.
Audit Commands
The following commands can be used to check for and fix dependency vulnerabilities in JavaScript applications:
- npm audit: Scans your project's dependency tree for known security vulnerabilities, reporting severity levels and affected packages.
- pnpm audit: Provides similar functionality for pnpm users, identifying vulnerable dependencies with detailed reports.
- pnpm audit --fix: Automatically updates vulnerable packages to patched versions where possible, resolving security issues without manual intervention. The npm equivalent is
npm audit fix
.
Best Practices
Run audits regularly during development and in CI/CD pipelines. Review audit reports carefully before applying automatic fixes, as updates might introduce breaking changes. Consider using tools like
npm ci
for production builds to ensure consistent, secure deployments. -
Challenge
Fixing Corrupt node_modules
There are times when your application fails to run due to corrupt
node_modules
files or mismatched package versions. Some common scenarios where this may occur include:-
Corrupted Installation: Module installation interrupted by system crashes, network issues, or
Ctrl+C
during install can leave dependencies in a broken state. -
Version Conflicts: Switching between Node.js versions, encountering conflicting peer dependencies, or using mismatched package versions can cause runtime errors and build failures.
-
Cache Issues: Stale npm/yarn/pnpm caches containing outdated or corrupted package data—especially after network interruptions or registry changes—can lead to unexpected behavior.
-
Lock File Mismatches: Discrepancies between
package.json
and lock files (package-lock.json
,yarn.lock
,pnpm-lock.yaml
) can cause inconsistent installations across environments. -
Platform Migration: Moving projects between different operating systems or architectures, where native modules may need to be recompiled.
These issues often prompt developers to perform a clean installation by deleting the
node_modules
folder and associated lock files.Here's a handy command to help recover from such problems:
# Remove everything rm -rf node_modules package-lock.json npm cache clean --force npm install # For pnpm rm -rf node_modules pnpm-lock.yaml pnpm store prune pnpm install
This approach resolves most dependency-related issues by ensuring clean, fresh installations.
-
-
Challenge
Other Alternatives to npm
Package managers have evolved to address npm's limitations, such as performance bottlenecks, disk space usage, and dependency resolution issues. First came Yarn, then pnpm, and now some runtimes come bundled with their own package managers, for example, Deno and Bun.
Yarn Classic vs. Yarn Berry
Yarn Classic (v1) introduced deterministic installs with lock files and parallel downloads, solving npm’s early inconsistency problems. Teams adopted it for faster, more reliable builds.
Yarn Berry (v2+) revolutionized dependency management with Plug'n'Play (PnP), eliminating
node_modules
folders entirely. Dependencies are stored in zip files with direct module resolution, dramatically reducing install times and disk usage.Bun: The Speed Demon
Bun combines a package manager, runtime, and bundler into one tool. Written in Zig, it is 10–25x faster than npm for installations. Its built-in JavaScript runtime competes with Node.js while maintaining compatibility.
When to Consider Alternatives
You should consider alternatives to npm for the following reasons:
- Large monorepos requiring faster installs (pnpm, Yarn Berry)
- Teams needing consistent environments (Yarn Classic)
- Performance-critical projects (Bun)
- Modern architectures embracing PnP (Yarn Berry)
-
Challenge
Migrating From npm to pnpm
Migrating between package managers is simple for most cases. In those cases, you could delete the lock file and
node_modules
folder, then reinstall all the packages. Yarn v1 and pnpm has theimport
command, that generates a lock file based onpackage-lock.json
. pnpm takes this further to support migratingnpm-shrinkwrap.json
andyarn.lock
files.For the next task, you're going to migrate a npm project to use pnpm.
-
Challenge
Putting It All Together
Let's imagine a scenario where your team has been assigned a new project. You're asked to set up the JavaScript project, using Express as the framework, and Prettier for formatting rules.
The project folder (in
step-09
) has been created, which includes apackage.json
file that comes when youpnpm init
in a folder.The following steps will guide you in doing setting up an Express project, with scripts to run the app or fix formatting issues. The
start
anddev
scripts is used to run the Express app. Thedev
script is used for development where you need to watch for file changes, and restart when files change. Theformat
script fixes any Prettier issues, whileformat:check
shows what files has issues without fixing them.Next, we're going to add
index.js
with a simple Express set up. You get a warning when you run that command:Checking formatting... [warn] index.js [warn] Code style issues found in the above file. Run Prettier with --write to fix.
You can fix that using the
format
script. Now that the formatting issues are fixed, the next step is to run the app and see it working When you're done trying the app, you can terminate the process using CTRL + C. -
Challenge
Outro
Congratulations!
You've mastered the essential skills for modern JavaScript package management through hands-on experience.
The focus was on npm and pnpm, while briefly covering other package managers.
npm: The industry standard, offering maximum compatibility and extensive documentation.
pnpm: Offers superior disk space efficiency through content-addressable storage, strict dependency resolution that prevents phantom dependencies, and significantly faster installation times. Ideal for large projects and monorepos.
Best Practices
Always commit lock files to ensure consistent environments across your team. Use
npm ci
in CI/CD pipelines for reproducible builds rather thannpm install
.Conduct regular security audits with
npm audit
to identify and fix vulnerabilities promptly.Quick Command Reference
- Initialize:
npm init
/pnpm init
- Install:
npm install
/pnpm install
- Clean install:
npm ci
/pnpm install --frozen-lockfile
- Add package:
npm add
/pnpm add
- Audit:
npm audit
/pnpm audit
You're now equipped to confidently manage dependencies, troubleshoot issues, and choose the right package manager for your JavaScript projects.
- Initialize:
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.