Glossary

Yarn

Yarn manages JavaScript package versions and installation, project commands, and workspaces. It is not a JavaScript runtime, a package registry, or a tool for orchestrating a monorepo build graph.

Short definition

A dependency manager with several installation strategies.

JavaScript projects declare direct dependencies, acceptable version ranges, and scripts in package.json. Yarn uses those declarations, the project configuration, and an existing yarn.lock to resolve the complete tree, including transitive dependencies. It records resolved versions and integrity data in the lockfile so the team and CI can repeat the same resolution.

Modern Yarn uses Plug’n’Play, or PnP, as its default installation strategy. Instead of a conventional node_modules directory, it creates a .pnp.cjs loader that maps package requests to their real locations. A project can also select the stable node-modules linker or pnpm linker in .yarnrc.yml; the installation layout therefore depends on the configuration, not merely on using Yarn.

Node.js is the runtime in which JavaScript executes, while Yarn is a development tool for package management. npm solves a similar problem with a different client, configuration, and lockfile. The public npm registry or a private registry is a separate network service that Yarn communicates with; it is neither part of Yarn nor a synonym for it.

The problem it solves

Keeps project dependencies and commands repeatable.

Without a package manager, a team would select versions manually, download archives, and discover compatible transitive dependencies itself. Yarn standardises that process, but the project must still verify the security and correctness of the code it selects.

  • add, update, and remove libraries and development tools
  • reproduce an approved dependency tree from yarn.lock
  • run tests, linting, builds, or a local server through scripts in package.json
  • manage multiple applications and shared packages in one workspace project
  • use public and private registries according to configuration and permissions
  • choose an installation strategy that fits tool compatibility and team requirements

Practical example

Two applications share one UI package.

The root package.json defines apps/web, apps/admin, and packages/ui as workspaces. Each part has its own manifest and declares only the dependencies it actually uses. An application can declare the internal package as "@shop/ui": "workspace:^", for example, so Yarn resolves it against the workspace with that name and preserves a corresponding version range when the package is published.

yarn install runs at the root and works with one project-wide yarn.lock. The yarn test:web script specifically invokes the test task from the @shop/web workspace. Yarn discovers the packages and makes their dependencies available; it does not automatically derive a build graph or provide a remote output cache.

Root package.json

{
  "name": "shop-workspace",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "test:web": "yarn workspace @shop/web test"
  }
}

How installation works

package.json → resolution → yarn.lock → fetch → link → use.

Installation is more than copying files. Yarn first determines a concrete dependency tree, then prepares packages using the strategy selected by the project.

  1. Manifests Yarn reads the root package.json and workspace manifests, including their regular, development, optional, and peer dependencies.
  2. Resolution It turns ranges and protocols into concrete packages. An existing yarn.lock preserves the previous result while it still satisfies the declarations.
  3. Fetch Yarn retrieves missing packages from the configured registry or another declared source and verifies the available integrity data.
  4. Link Depending on nodeLinker, Yarn creates a PnP map, a traditional node_modules tree, or a pnpm-style structure with symlinks and hardlinks.
  5. Build and scripts Depending on configuration, installation may run permitted build lifecycle scripts. Project commands can then be invoked with yarn run or the shorter yarn <name> form.

Key concepts

The manifest, lockfile, linker, and workspaces have different responsibilities.

A well-configured project versions these layers together without confusing their roles.

package.json

The manifest describes a package: its name, scripts, workspaces, and dependency, devDependency, or peerDependency ranges. The packageManager field can pin a specific Yarn version for tools that honour it.

yarn.lock

The generated lockfile records the concrete resolutions for the entire project and belongs in version control. It should not be edited manually or casually replaced by another package manager’s lockfile.

Dependency resolution

Yarn distinguishes a package request from its concrete resolution. A semver range alone does not select one version; the result also depends on the lockfile, available releases, peer dependencies, protocols, and project settings.

Scripts

Entries in the scripts field provide shared team commands and expose executable tools from local dependencies. Installation lifecycle scripts from third-party packages can execute code depending on configuration, so they require security review.

Workspaces

A workspace is an individual package within a single Yarn project. Workspaces simplify shared installation and local linking, but do not define application architecture or the full dependency graph of build tasks by themselves.

PnP and other linkers

PnP is the current default and uses .pnp.cjs without node_modules. The node-modules and pnpm linkers are both stable options; choosing the latter selects a pnpm-style layout, not the pnpm package manager.

Benefits, limitations, and common mistakes

Stricter resolution helps, but compatibility still needs to be verified.

Benefits

  • one versioned lockfile for the project’s applications and packages
  • native workspace linking and an explicit workspace: protocol
  • an optional PnP model that exposes undeclared dependencies and avoids managing a node_modules tree
  • consistent scripts and a pinned package manager version for local development and CI

Limitations and common mistakes

  • some tools need an adjustment, editor SDK, or packageExtensions to work with PnP
  • mixing yarn.lock with package-lock.json and switching package managers harms reproducibility
  • an uncommitted or arbitrarily replaced lockfile can change transitive dependencies
  • installation scripts and packages are supply-chain code, not inert data
  • a workspace project without clear boundaries can become a tightly coupled monorepo

Practical use and comparison

Yarn manages packages; other layers handle execution and orchestration.

Yarn and npm are package managers. Both read package.json, install dependencies, and run scripts, but each uses its own lockfile, configuration, and installation model. A project should select one tool, pin its version, and use it consistently in local development and CI.

Node.js runs the application and most JavaScript tooling. Yarn can make a particular library or CLI available, but it is not a runtime and does not decide the supported Node.js version on the project’s behalf. A registry is a remote package source; Yarn can use the public npm registry or a controlled private source.

Turborepo addresses another layer of a monorepo: it schedules tasks according to their dependencies and caches their outputs. Yarn workspaces primarily define packages, resolve their dependencies, and link them locally. The tools can work together, but neither automatically replaces the other.

For a single application, Yarn can still provide one lockfile and the chosen linker without requiring a monorepo. Workspaces make sense when two applications genuinely share a package or their changes need to be versioned together. The mere presence of apps and packages directories is not a reason to combine unrelated systems in one repository.

PnP is worth trying in a new project because it makes dependency declarations stricter and avoids a traditional node_modules directory. If a target tool does not support PnP and fixing it is not economically sensible, the stable node-modules linker is a legitimate compatibility choice. Record the decision in the versioned .yarnrc.yml and verify it across development, tests, and builds.

Security and quality

The lockfile, Yarn version, and configuration form one unit.

A reproducible installation requires identical inputs and controlled changes, not merely the same command.

  • commit package.json, yarn.lock, .yarnrc.yml, and other intentionally versioned Yarn files together
  • pin the package manager version and verify that local environments and CI actually use it
  • use yarn install --immutable in CI so mismatched manifests and lockfiles fail the build
  • review changes to direct and transitive dependencies, the package source, and lifecycle scripts
  • never store registry tokens in package.json, yarn.lock, or shared repository configuration
  • with PnP, test the editor, test runner, bundler, and deployment; do not conceal a problem by importing an undeclared dependency
  • do not maintain lockfiles from multiple package managers in one project without an explicit, documented reason

Common questions

Yarn without outdated assumptions

Is Yarn a JavaScript runtime?

No. Node.js is one example of a runtime. Yarn is a package manager that resolves dependencies and runs project scripts through an available runtime.

Does modern Yarn always create node_modules?

No. Modern Yarn defaults to Plug’n’Play with a .pnp.cjs loader. A project can select the stable node-modules or pnpm mode through nodeLinker instead.

What is the difference between package.json and yarn.lock?

package.json declares direct dependencies and acceptable ranges. yarn.lock records the project’s concrete resolved tree so later installations do not repeat the selection from scratch.

Are Yarn workspaces the same as Turborepo?

No. Workspaces define and link packages within one Yarn project. Turborepo schedules tasks and caches their outputs across a monorepo; it can use Yarn workspaces.

Should yarn.lock be committed to Git?

Yes, for a team application. The lockfile should be versioned and reviewed with the manifest change so developers and CI install the same dependency resolutions.

Hands-on experience

Development tools should support repeatable builds and clear project boundaries.

When working on web applications, I consider dependencies, CI, and repository structure together so local development matches the verified deployment process.

Request a call

I will call you on the next working day between 9:00 and 17:00.

You can also call me directly.

+420 605 181 728

Leave your phone number and send a callback request.

By sending, you agree to processing your data in order to handle your request.