| |

Yarn 05 ๐Ÿงถ Adding, Upgrading, and Removing Packages

โฑ๏ธ Estimated read: 9 min | |

Package management is the daily rhythm of working with Yarn. You add a library to solve a problem, upgrade it when a bug is fixed or a feature lands, and remove it when the dependency is no longer needed. Each of these operations modifies two filesโ€”package.json and yarn.lockโ€”and the commands that perform them differ significantly between Yarn Classic (1.x) and Yarn Berry (2+). The most consequential divergence is the upgrade command: yarn upgrade is a Classic concept, and Berry replaced it with yarn up .

Key point: Adding and removing packages are consistent across Yarn versions, but upgrading is not. yarn upgrade belongs to Yarn Classic; yarn up is the Berry equivalent, and it upgrades across the entire project rather than a single workspace.


Why the commands differ

The Classic legacy. Yarn 1.x provided yarn upgrade with a rich set of flags: upgrade within the declared range, upgrade to latest while ignoring the range, upgrade by scope, upgrade by pattern. It was a flexible command, but it operated on a single workspace and required explicit flags to cross major versions .

The Berry redesign. Yarn 2+ replaced yarn upgrade with yarn up. The new command makes a different default choice: it upgrades to the latest version across the entire project, ignoring the ranges previously declared in package.json. This is closer to Classic’s yarn upgrade --latest than to plain yarn upgrade . The rename was not cosmeticโ€”it signaled a shift from “upgrade within constraints” to “upgrade to latest, everywhere.”

The removal command is stable. yarn remove exists in both versions with nearly identical behavior. It removes the package from the manifest, prunes it from the lockfile, and runs an install to clean up the project. Berry adds a --all flag for monorepos and accepts glob patterns .

The trade-off. Berry’s yarn up is faster for project-wide updates but less precise for single-package control. Classic’s yarn upgrade is more granular but confined to one workspace. The right command depends on which version you are running and whether you need to cross major version boundaries deliberately.


a. Adding packages: yarn add

yarn add installs a package and writes it to the manifest. The default destination is dependencies. Flags redirect it to devDependencies, peerDependencies, or optionalDependencies .

# Add to dependencies (runtime)
yarn add express

# Add to devDependencies (build, test, lint)
yarn add --dev typescript

# Add a specific version
yarn add lodash@4.17.21

# Add a tag
yarn add react@beta

The version range written to package.json depends on how you specify the package. An unqualified name resolves to the latest tag and receives a caret range (^1.2.3) by default. An explicit version or range is written as-is. The --exact, --tilde, and --caret flags override the default modifier .

If the package already exists in dependencies or devDependencies, yarn add upgrades it in place. Peer dependencies are never modified unless --peer is explicitly passed .


b. Upgrading packages: yarn up (Berry) and yarn upgrade (Classic)

In Yarn Berry, yarn up is the upgrade command. It updates packages to their latest versions across the entire project, ignoring the ranges declared in the manifest. It affects dependencies and devDependencies in all workspaces, but leaves peerDependencies unchanged .

# Upgrade a specific package to latest across all workspaces
yarn up lodash

# Upgrade to a specific version
yarn up lodash@4.17.21

# Upgrade all packages matching a scope
yarn up '@babel/*'

# Interactive mode: choose which upgrades to apply
yarn up --interactive

The --recursive flag refreshes lockfile resolutions without editing the manifest. This is useful when you want to re-resolve transitive dependencies without changing the declared ranges in package.json . The -C, -E, and -T flags control the semver modifier written when the command updates the manifest.

In Yarn Classic, yarn upgrade remains available. Without flags, it upgrades within the ranges declared in package.json. With --latest, it ignores the ranges and upgrades to the latest version, potentially crossing major versions .

# Classic: upgrade within declared ranges
yarn upgrade

# Classic: upgrade to latest, ignoring ranges
yarn upgrade --latest

The distinction matters for migration. If you are moving from Classic to Berry, yarn upgrade --latest maps to yarn up, not to yarn upgrade .


c. Removing packages: yarn remove

yarn remove deletes a package from the manifest and prunes it from the lockfile. It removes the package from whichever dependency field it occupiesโ€”dependencies, devDependencies, or any otherโ€”and runs an install to clean up the project .

# Remove a single package
yarn remove lodash

# Remove from all workspaces (Berry)
yarn remove lodash --all

# Remove by glob pattern (escape to prevent shell expansion)
yarn remove 'eslint-*'

The glob pattern support is a Berry addition. In a monorepo, --all removes the package from every workspace rather than only the current one . After removal, Yarn updates yarn.lock to prune the package and any transitive dependencies that are no longer required by any remaining package.


Complete Example Session

# ============================================
# PART 1: ADDING A RUNTIME DEPENDENCY
# ============================================

# Default destination: dependencies
yarn add express
# package.json: "express": "^4.18.2"
# yarn.lock: express@^4.18.2 resolved
# ============================================
# PART 2: ADDING A DEV DEPENDENCY
# ============================================

# --dev writes to devDependencies
yarn add --dev jest
# package.json: "jest": "^29.7.0" (devDependencies)
# yarn.lock: jest@^29.7.0 resolved
# ============================================
# PART 3: ADDING A SPECIFIC VERSION
# ============================================

# Exact version, no caret
yarn add lodash@4.17.21
# package.json: "lodash": "4.17.21"
# yarn.lock: lodash@4.17.21 resolved
# ============================================
# PART 4: UPGRADING WITH YARN UP (BERRY)
# ============================================

# Upgrades across all workspaces, ignores ranges
yarn up express
# package.json: "express": "^5.0.1" (range updated)
# yarn.lock: express@^5.0.1 resolved
# ============================================
# PART 5: UPGRADING WITH INTERACTIVE MODE
# ============================================

# Offers choices for each upgrade path
yarn up --interactive
# Prompts for each package with available upgrades
# ============================================
# PART 6: UPGRADING WITHIN RANGE (CLASSIC)
# ============================================

# Yarn Classic: stays within declared range
yarn upgrade express
# package.json: "express": "^4.18.0" (unchanged)
# yarn.lock: upgraded to latest 4.x.x
# ============================================
# PART 7: REMOVING A PACKAGE
# ============================================

yarn remove lodash
# package.json: lodash entry removed
# yarn.lock: lodash and unused transitive deps pruned
# ============================================
# PART 8: REMOVING FROM ALL WORKSPACES (BERRY)
# ============================================

# Monorepo: remove from every workspace
yarn remove lodash --all
# Removed from all workspace manifests
# ============================================
# PART 9: REMOVING BY GLOB PATTERN (BERRY)
# ============================================

# Escape the glob to prevent shell expansion
yarn remove 'eslint-*'
# Removes eslint-core, eslint-plugin-*, etc.

The nine parts above cover the lifecycle: adding runtime and dev dependencies, pinning exact versions, upgrading with Berry’s yarn up, interactive upgrades, Classic’s range-constrained yarn upgrade, removing single packages, removing from all workspaces, and removing by glob pattern.


Quick Reference

Add Commands

CommandDestination
yarn add <pkg>dependencies
yarn add -D <pkg>devDependencies
yarn add -P <pkg>peerDependencies
yarn add -O <pkg>optionalDependencies
yarn add <pkg>@<version>Exact version
yarn add <pkg>@<tag>Tag

Upgrade Commands by Version

ActionYarn Classic (1.x)Yarn Berry (2+)
Upgrade within rangeyarn upgrade(not applicable)
Upgrade to latestyarn upgrade --latestyarn up
Upgrade specific packageyarn upgrade <pkg>yarn up <pkg>
Upgrade by scopeyarn upgrade --scope @orgyarn up '@org/*'
Interactiveyarn upgrade-interactiveyarn up -i

Remove Commands

CommandEffect
yarn remove <pkg>Remove from current workspace
yarn remove <pkg> --allRemove from all workspaces (Berry)
yarn remove '<glob>'Remove matching packages (Berry)

Best Practices

โœ… Do This:

yarn add express
<!-- Use CLI, never edit package.json manually -->   # โœ…
yarn add --dev typescript
<!-- Build tools belong in devDependencies -->       # โœ…
yarn up lodash --interactive
<!-- Review each upgrade before applying -->         # โœ…
yarn remove lodash
<!-- Removes from manifest and lockfile -->          # โœ…

โŒ Don’t Do This:

# Manual edit of package.json + yarn install
<!-- Risks version range typos -->                   # โŒ
yarn upgrade lodash
# In Berry: "Couldn't find a script named upgrade"    # โŒ
# Ignore peerDependencies when upgrading
<!-- yarn up leaves peers unchanged -->              # โŒ
yarn remove 'eslint-*'
# Unescaped glob: shell may expand before Yarn sees it # โŒ

Common Pitfalls

PitfallWhy It HappensFix
yarn upgrade not found in BerryCommand renamed to yarn upUse yarn up <pkg>
Upgrade crosses major version unexpectedlyyarn up ignores declared rangesUse --interactive or pin explicitly
Peer dependency unchanged after upgradeyarn up leaves peers aloneEdit peerDependencies manually or use yarn add -P
Glob pattern expands in shellShell processes * before YarnQuote the pattern: 'pkg-*'
Removed package still in lockfileTransitive dependency of another packageCheck yarn why before assuming removal failed

Real-World Examples

1. Add Runtime Dependency

yarn add express

2. Add Dev Dependency

yarn add --dev vitest

3. Add Exact Version

yarn add lodash@4.17.21

4. Add from Tag

yarn add react@beta

5. Upgrade One Package (Berry)

yarn up axios

6. Upgrade All (Berry)

yarn up '*'

7. Interactive Upgrade

yarn up --interactive

8. Remove One Package

yarn remove lodash

9. Remove from All Workspaces

yarn remove lodash --all

10. Remove by Pattern

yarn remove 'eslint-*'

Visual

Add: Manifest and Lockfile Update

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  yarn add express                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  package.json                                โ”‚
โ”‚  "dependencies": {                           โ”‚
โ”‚    "express": "^4.18.2"                      โ”‚
โ”‚  }                                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  yarn.lock                                   โ”‚
โ”‚  express@^4.18.2:                            โ”‚
โ”‚    version "4.18.2"                          โ”‚
โ”‚    integrity sha512-...                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Adding a package writes the range to the manifest and the exact resolution to the lockfile. Both files are committed.

Upgrade: Classic vs Berry

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Upgrade express                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                     โ”‚
        โ–ผ                     โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Yarn Classic  โ”‚     โ”‚ Yarn Berry    โ”‚
โ”‚               โ”‚     โ”‚               โ”‚
โ”‚ yarn upgrade  โ”‚     โ”‚ yarn up       โ”‚
โ”‚               โ”‚     โ”‚               โ”‚
โ”‚ Stays within  โ”‚     โ”‚ Ignores range โ”‚
โ”‚ declared rangeโ”‚     โ”‚ Upgrades to   โ”‚
โ”‚               โ”‚     โ”‚ latest        โ”‚
โ”‚ Single        โ”‚     โ”‚ Across all    โ”‚
โ”‚ workspace     โ”‚     โ”‚ workspaces    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The command name encodes the philosophy: Classic upgrades within constraints, Berry upgrades to latest.

Remove: Pruning the Tree

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  yarn remove lodash                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  package.json                                โ”‚
โ”‚  "lodash": "^4.17.21" โ† deleted              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  yarn.lock                                   โ”‚
โ”‚  lodash@^4.17.21 โ† pruned                    โ”‚
โ”‚  (transitive deps pruned if unused)          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  yarn install runs automatically             โ”‚
โ”‚  Project is clean                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Removal is not just a manifest edit. It triggers a lockfile prune and an install to reflect the new dependency graph.


Summary

ItemValue
Add to runtimeyarn add <pkg>
Add to devyarn add -D <pkg>
Upgrade (Berry)yarn up <pkg>
Upgrade within range (Classic)yarn upgrade <pkg>
Upgrade to latest (Classic)yarn upgrade <pkg> --latest
Removeyarn remove <pkg>
Remove from all workspacesyarn remove <pkg> --all
Interactive upgradeyarn up --interactive
Glob removalyarn remove '<pattern>' (escaped)

Key takeaways:

  • yarn add is stable across versions. It writes to the manifest and resolves into the lockfile. Flags redirect the destination field .
  • yarn upgrade is Classic-only. Berry replaced it with yarn up, which upgrades to latest across all workspaces and ignores declared ranges .
  • yarn up leaves peerDependencies unchanged. This is deliberateโ€”peers are contracts with consumers, not dependencies to resolve .
  • yarn remove prunes the lockfile. Removing a direct dependency also removes any transitive dependencies that no other package requires .
  • Glob patterns require escaping. Quote the pattern to prevent the shell from expanding it before Yarn sees it .
  • Version choice matters for migration. If you rely on yarn upgrade --latest in Classic, the Berry equivalent is yarn up, not yarn upgrade.

Remember: Adding and removing packages are mechanical operations with predictable outcomes. Upgrading is where the versions diverge. Classic’s yarn upgrade respects the ranges you declared; Berry’s yarn up ignores them and upgrades to latest everywhere. Know which Yarn you are running, and choose the upgrade command that matches your intent.

Was this helpful?


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!