Back to Scaling Node.js Applications guides

Getting Started with Yarn: A Comprehensive Guide

Stanley Ulili
Updated on March 19, 2025

Yarn transformed JavaScript package management when Facebook introduced it in 2016 to fix significant speed and reliability issues with npm. It downloads packages in parallel, caches efficiently, and verifies files to ensure smooth and consistent installs across teams while remaining compatible with the npm registry.

Its most significant strength is predictable builds, guaranteeing the same dependencies for everyone, no matter when or where they install them. This prevents frustrating inconsistencies that often cause code to run differently on different setups.

This guide covers Yarn from installation to advanced features, helping you maximize its speed and reliability while avoiding common dependency issues.

Prerequisites

Before diving into Yarn, ensure you have Node.js version 22.x or later installed on your development machine. This tutorial assumes familiarity with fundamental Node.js package management concepts like dependencies, version constraints, and the package.json file structure.

Getting started with Yarn

Let's start a new project to get hands-on experience with Yarn. This practical approach will give you a clear understanding of how Yarn works and what makes it different from other package managers.

First, install Yarn globally through npm with:

 
npm install --global yarn

Alternatively, platform-specific installation options (including installers for Windows, macOS, and Linux distributions) are available in the official Yarn documentation.

Verify your installation by checking Yarn's version:

 
yarn --version
Output
1.22.22

Now, create and navigate to a new project directory:

 
mkdir yarn-demo && cd yarn-demo

Initialize your project using Yarn's interactive prompts:

 
yarn init

You'll see a series of prompts asking for details about your project. If you're unsure, you can simply press Enter to accept the defaults:

Output

yarn init v1.22.22
question name (yarn-demo): 
question version (1.0.0): 
question description: 
question entry point (index.js): 
question repository url: 
question author: 
question license (MIT): 
question private: 
success Saved package.json
✨  Done in 28.24s.

This creates a package.json file, which stores essential project details and dependencies. You can edit it later as needed.

package.json
{
  "name": "yarn-demo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT"
}

Let's install Express as our first dependency to see Yarn in action:

 
yarn add express
Output

yarn add v1.22.22
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] đźšš  Fetching packages...
[3/4] đź”—  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
success Saved 41 new dependencies.
info Direct dependencies
└─ express@4.21.2
info All dependencies
...

Yarn creates both a node_modules directory and a yarn.lock file—which we'll explore shortly.

Create a simple Express application to test your setup:

index.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello from Yarn!');
});

const port = 3000;
app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

Start the server with:

 
node index.js

Visit http://localhost:3000 in your browser to see your "Hello from Yarn!" message:

Screenshot of the browser with the welcome message

Then, stop the server with Ctrl + C when finished.

Understanding Yarn's dependency management

Yarn takes a big step forward in how JavaScript projects manage dependencies, focusing on both speed and reliability. A key part of this is its advanced lockfile system, which ensures consistency across different environments.

At the heart of Yarn's approach is yarn.lock, a file that records exact package versions, content hashes, and the entire dependency tree. Unlike package.json, which allows version ranges, yarn.lock guarantees that every installation gets the same dependencies, preventing unexpected issues.

Now, let's take a look at the project structure Yarn generates.

 
ls -la
Output
total 64
drwxr-xr-x@  6 stanley  staff    192 Mar 19 16:14 .
drwxr-xr-x@  4 stanley  staff    128 Mar 19 16:10 ..
-rw-r--r--@  1 stanley  staff    235 Mar 19 16:18 index.js
drwxr-xr-x@ 71 stanley  staff   2272 Mar 19 16:13 node_modules
-rw-r--r--@  1 stanley  staff    140 Mar 19 16:13 package.json
-rw-r--r--@  1 stanley  staff  21747 Mar 19 16:13 yarn.lock

The yarn.lock file contains detailed metadata about every installed package:

 
head -n 15 yarn.lock
Output
 THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


accepts@~1.3.8:
  version "1.3.8"
  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
  integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
  dependencies:
    mime-types "~2.1.34"
    negotiator "0.6.3"

array-flatten@1.1.1:
  version "1.1.1"
  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"

Yarn improves package management in four major ways:

  • Predictable Installs – By locking exact versions and checksums, Yarn prevents issues where dependencies work in development but break in production due to small version changes.

  • Offline Mode – Yarn caches packages locally, allowing you to reinstall dependencies even without an internet connection. This is especially useful for working on flights, in areas with weak connectivity, or when package registries are down.

  • Faster Installs – Unlike older package managers that install dependencies one at a time, Yarn processes multiple downloads at once, significantly speeding up installations—especially for large projects.

  • Better Reliability – If a package download fails due to network issues, Yarn automatically retries using alternative sources instead of failing the entire installation. This is crucial for CI/CD pipelines and automated deployments.

To demonstrate Yarn's offline capabilities, let's remove and reinstall dependencies without an internet connection:

 
rm -rf node_modules
 
yarn install --offline
Output
yarn install v1.22.22
[1/4] 🔍  Resolving packages...
[2/4] đźšš  Fetching packages...
[3/4] đź”—  Linking dependencies...
[4/4] 🔨  Building fresh packages...
✨  Done in 0.26s.

The installation completes rapidly because Yarn uses cached packages instead of downloading them again—a feature that significantly accelerates CI/CD pipelines and deployment processes.

Managing dependencies with Yarn

Yarn provides an intuitive command set that makes dependency management straightforward while offering powerful features beyond basic installation. These commands follow logical patterns that are easy to remember and efficient in daily development workflows.

Installing dependencies

Add new dependencies to your project using the add command, which automatically updates package.json and yarn.lock:

 
yarn add lodash
Output
yarn add v1.22.22
[1/4] 🔍  Resolving packages...
[2/4] đźšš  Fetching packages...
[3/4] đź”—  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ lodash@4.17.21
info All dependencies
└─ lodash@4.17.21
✨  Done in 1.31s.

For development-only dependencies (like testing frameworks or build tools), use the -D flag to add them to devDependencies:

 
yarn add -D jest

When you need a specific package version (for compatibility or to avoid breaking changes), specify it directly:

 
yarn add react@17.0.2

This pinned version approach is particularly valuable when working with libraries that have breaking changes between major releases.

Installing all dependencies

After cloning a project or switching branches, install all dependencies with a single command:

 
yarn install

Yarn's intelligent caching dramatically speeds up this process compared to other package managers. For even greater convenience, simply typing yarn (with no additional arguments) acts as an alias for yarn install.

Updating dependencies

Keeping dependencies current while respecting version constraints is crucial for security and performance. Check for outdated packages with:

 
yarn outdated
Output
yarn outdated v1.22.22
info Color legend : 
 "<red>"    : Major Update backward-incompatible updates 
 "<yellow>" : Minor Update backward-compatible features 
 "<green>"  : Patch Update backward-compatible bug fixes
Package Current Wanted Latest Package Type URL               
react   17.0.2  17.0.2 19.0.0 dependencies https://react.dev/
✨  Done in 7.15s.

Update all dependencies within your version constraints using:

 
yarn upgrade

For targeted updates of specific packages:

 
yarn upgrade lodash

Removing dependencies

Cleanly remove packages and update your package.json with:

 
yarn remove lodash
Output
yarn remove v1.22.22
[1/2] đź—‘  Removing module lodash...
[2/2] 🔨  Regenerating lockfile and installing missing dependencies...
success Uninstalled packages.
✨  Done in 0.50s.

Yarn automatically updates the lockfile and cleans up the node_modules directory, ensuring no orphaned packages remain.

Script execution

Yarn streamlines the execution of package.json scripts with a simplified syntax. Define your application scripts:

package.json
{
  ...
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest"
  }
}

Unlike npm, Yarn doesn't require the run keyword for most scripts—making commands shorter and more intuitive:

 
yarn start
 
yarn test

Pass additional arguments to scripts using the double-dash syntax:

 
yarn test --watchAll

This cleaner syntax makes development workflows more efficient, particularly when executing test or build processes frequently.

Listing installed packages

Gain visibility into your project's dependencies with:

 
yarn list

For a more focused view that shows only direct dependencies:

 
yarn list --depth=0

This command helps identify unexpected or duplicate dependencies that might increase your bundle size.

Auditing dependencies for security issues

Security vulnerabilities in dependencies can expose your application to serious risks. Scan your project for known security issues:

 
yarn audit

Yarn checks your dependencies against a database of known vulnerabilities and provides detailed information about potential risks and remediation strategies.

Working with Yarn's lockfile

The yarn.lock file is the foundation of Yarn's deterministic installations and one of its most important innovations. This file encodes precise information about your dependency tree that goes far beyond what package.json can express.

When examining yarn.lock, you'll find it contains:

  • Exact versions for every package in your dependency tree
  • Cryptographic checksums to verify package integrity
  • Resolution strategies for packages with conflicting peer dependencies
  • Metadata about where packages were sourced from
  • Detailed version resolution records for hierarchical dependencies

This comprehensive approach ensures complete reproducibility—a developer installing dependencies in Tokyo gets exactly the same packages as a CI server running in Berlin, down to the byte.

Some key principles for working with yarn.lock:

  • Always commit yarn.lock to version control alongside package.json
  • Never manually edit yarn.lock—let Yarn manage it
  • Use --frozen-lockfile in CI/CD environments to ensure no lockfile changes during builds
  • When resolving merge conflicts, prioritize careful merging of yarn.lock to maintain consistency

For deployment or CI environments where you want to ensure the lockfile remains unchanged:

 
yarn install --frozen-lockfile

This flag causes the installation to fail if any changes to yarn.lock would be required, safeguarding against unexpected dependency changes during automated processes.

Final thoughts

Yarn has become a key tool in modern JavaScript development, solving major package management issues with its focus on consistent installs, speed, and ease of use. It’s an excellent choice for projects of any size.

For an alternative, consider pnpm, which offers similar benefits while using a unique content-addressable storage system to save disk space and speed up installations.

Author's avatar
Article by
Stanley Ulili
Stanley Ulili is a technical educator at Better Stack based in Malawi. He specializes in backend development and has freelanced for platforms like DigitalOcean, LogRocket, and AppSignal. Stanley is passionate about making complex topics accessible to developers.
Got an article suggestion? Let us know
Next article
Getting Started with Sequelize ORM
Learn how to use Sequelize with SQLite in Node.js to build a complete data-driven application. This step-by-step guide covers setup, model creation, querying, updating, and deleting records using Sequelize's modern, async/await-friendly API.
→
Licensed under CC-BY-NC-SA

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Make your mark

Join the writer's program

Are you a developer and love writing and sharing your knowledge with the world? Join our guest writing program and get paid for writing amazing technical guides. We'll get them to the right readers that will appreciate them.

Write for us
Writer of the month
Marin Bezhanov
Marin is a software engineer and architect with a broad range of experience working...
Build on top of Better Stack

Write a script, app or project on top of Better Stack and share it with the world. Make a public repository and share it with us at our email.

community@betterstack.com

or submit a pull request and help us build better products for everyone.

See the full list of amazing projects on github