Yarn 10 🧶 Configuring Yarn with .yarnrc.yml
The .yarnrc.yml file is the central configuration hub for Yarn Berry (2+). Every project-level setting—how packages are linked, where the cache lives, which registry is queried, how workspaces behave—lives in this single YAML file. Unlike package.json, which is shared with npm and the broader Node.js ecosystem, .yarnrc.yml is Yarn-specific and is the only file that controls Yarn’s internal behavior. A misconfigured .yarnrc.yml can silently change the linker, bypass security settings, or prevent the project from installing at all.
Key point: .yarnrc.yml must be committed to version control. It defines the contract for how Yarn behaves in the project, and every developer and CI runner must use the same configuration.
Why .yarnrc.yml exists
The Yarn 1 legacy problem. Yarn Classic (1.x) used .yarnrc and a collection of .npmrc fallbacks. These files were inconsistent, poorly documented, and often inherited settings from npm in ways that were difficult to trace. Yarn Berry replaced this with a single, explicit YAML file that contains only Yarn’s settings. There is no fallback to .npmrc for Yarn-specific behavior; the configuration is isolated and predictable .
The linker problem. The most consequential setting in .yarnrc.yml is nodeLinker. It determines whether Yarn uses Plug’n’Play (the default in Yarn 4), a traditional node_modules directory, or a pnpm-style store. This choice affects every tool in the project—some work only with node-modules, others are optimized for PnP. The linker must be set deliberately, not left to a default that changes between Yarn versions .
The registry and authentication problem. When a project depends on packages from a private registry, .yarnrc.yml routes those requests with npmScopes and authenticates them with npmAuthToken. Without this configuration, Yarn queries the public npm registry, which either fails or—worse—resolves a malicious package with the same name from the public internet . The scoping mechanism is the defense against this class of dependency confusion attack.
The workspace problem. In a monorepo, .yarnrc.yml defines shared dependency versions through catalog: , controls hoisting behavior with nmHoistingLimits, and configures workspace profiles for shared dev dependencies . These settings are not expressible in individual package.json files; they are project-wide policies that belong in the root configuration.
The trade-off. .yarnrc.yml is a single source of truth, which makes configuration auditable. But it is also a single point of failure. A typo in nodeLinker changes the entire installation model. A missing npmAuthToken breaks every install from a private scope. The file must be reviewed with the same rigor as yarn.lock.
a. The linker and core installation settings
The nodeLinker setting determines how Yarn materializes the dependency graph on disk. The three supported values are pnp, node-modules, and pnpm .
# .yarnrc.yml
nodeLinker: pnp
enableGlobalCache: false
The pnp value is the Yarn 4 default. It generates the .pnp.cjs loader and does not create a node_modules directory. The node-modules value creates a traditional node_modules layout, which is necessary for compatibility with tools that assume filesystem resolution. The pnpm value creates a store-based layout similar to pnpm’s .
enableGlobalCache controls whether packages are stored in the machine-global cache (~/.yarn/berry/cache) or the project-local cache (.yarn/cache). Setting it to false is required for Zero-Installs and for CI environments where the project directory must be self-contained .
The yarnPath setting pins the Yarn binary to a specific release stored inside the project. This ensures that every developer and CI runner uses the exact same Yarn version, regardless of what is installed globally .
b. Registry configuration and security
The default registry is https://registry.yarnpkg.com, which mirrors npm. When a project needs packages from a private registry or a scoped organization, npmScopes routes requests by package prefix .
npmScopes:
my-company:
npmRegistryServer: "https://npm.internal.example.com"
npmAuthToken: "${INTERNAL_NPM_TOKEN}"
The npmAuthToken should never be hardcoded. Yarn supports environment variable interpolation with the ${VAR} syntax, allowing the token to be injected from CI secrets or a local .env file . The npmAlwaysAuth setting sends credentials on every request to a registry, but should only be enabled for private mirrors, not the public registry .
The enableStrictSsl setting must remain true. Disabling it to work around a corporate proxy error allows any network intermediary to intercept and modify package downloads. The correct fix is to install the proxy’s certificate authority on the build machine .
c. Workspace and catalog configuration
In a monorepo, .yarnrc.yml centralizes dependency versions through catalogs. A catalog is a named map of package names to version ranges. Workspaces reference the catalog with the catalog: protocol in their package.json, and the actual version is resolved from .yarnrc.yml .
catalog:
react: ^19.0.0
typescript: ^5.5.0
{
"dependencies": {
"react": "catalog:"
}
}
Named catalogs allow multiple version sets—for example, react18 and react19—to coexist in the same repository. Workspaces specify the catalog name after the colon: "react": "catalog:react18" .
Workspace profiles provide shared dev dependencies. A profile defined in .yarnrc.yml is applied to a workspace by adding an extends field to its package.json. This eliminates the need to repeat typescript, @types/node, and testing libraries in every workspace .
workspaceProfiles:
typescript:
devDependencies:
typescript: ^5.5.0
"@types/node": ^20.0.0
Complete Example Session
# ============================================
# PART 1: CREATE THE FILE
# ============================================
# At the repository root, create .yarnrc.yml.
touch .yarnrc.yml
# ============================================
# PART 2: SET THE LINKER
# ============================================
# Use node-modules for compatibility with existing tools.
echo "nodeLinker: node-modules" >> .yarnrc.yml
# ============================================
# PART 3: DISABLE GLOBAL CACHE
# ============================================
# Store packages in the project for Zero-Installs.
echo "enableGlobalCache: false" >> .yarnrc.yml
# ============================================
# PART 4: PIN THE YARN BINARY
# ============================================
# Use the Yarn 4.5.1 release stored in the project.
echo "yarnPath: .yarn/releases/yarn-4.5.1.cjs" >> .yarnrc.yml
# ============================================
# PART 5: CONFIGURE A PRIVATE SCOPE
# ============================================
# Route @my-company packages to the internal registry.
cat >> .yarnrc.yml <<EOF
npmScopes:
my-company:
npmRegistryServer: "https://npm.internal.example.com"
npmAuthToken: "\${INTERNAL_NPM_TOKEN}"
EOF
# ============================================
# PART 6: DEFINE A CATALOG
# ============================================
# Centralize shared dependency versions.
cat >> .yarnrc.yml <<EOF
catalog:
react: ^19.0.0
typescript: ^5.5.0
EOF
# ============================================
# PART 7: VERIFY THE CONFIGURATION
# ============================================
# Yarn prints the effective configuration.
yarn config
# Check that nodeLinker, enableGlobalCache, and npmScopes are correct.
# ============================================
# PART 8: COMMIT TO VERSION CONTROL
# ============================================
git add .yarnrc.yml
git commit -m "Add Yarn configuration"
# ============================================
# PART 9: CI USES THE SAME CONFIGURATION
# ============================================
# No additional configuration is needed in CI.
# The committed .yarnrc.yml ensures identical behavior.
yarn install --immutable
The nine parts trace the configuration lifecycle: creating the file, setting the linker, disabling the global cache, pinning the Yarn binary, configuring a private registry, defining a catalog, verifying the effective settings, committing the file, and running CI with the same configuration.
Quick Reference
Core Settings
| Setting | Values | Purpose |
|---|---|---|
nodeLinker | pnp, node-modules, pnpm | Dependency resolution model |
enableGlobalCache | true, false | Local vs global cache |
yarnPath | Path to .cjs | Pin Yarn version |
enableStrictSsl | true (default) | TLS certificate verification |
Registry Settings
| Setting | Purpose |
|---|---|
npmRegistryServer | Default registry URL |
npmScopes | Per-scope registry and auth |
npmAuthToken | Authentication token |
npmAlwaysAuth | Send credentials every request |
Workspace Settings
| Setting | Purpose |
|---|---|
catalog | Shared dependency versions |
catalogs | Named catalog sets |
workspaceProfiles | Shared dev dependencies |
Best Practices
✅ Do This:
nodeLinker: node-modules
<!-- Explicitly set the linker --> # ✅
npmAuthToken: "${INTERNAL_NPM_TOKEN}"
<!-- Use environment variable for secrets --> # ✅
catalog:
react: ^19.0.0
<!-- Centralize shared versions --> # ✅
❌ Don’t Do This:
enableStrictSsl: false
<!-- Disables TLS verification --> # ❌
npmAuthToken: "ghp_xxxxxxxxxxxx"
<!-- Hardcoded token in version control --> # ❌
# Leave nodeLinker unset
<!-- Defaults change between Yarn versions --> # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Tools fail after install | nodeLinker set to pnp | Set nodeLinker: node-modules |
| Private packages not found | Missing npmScopes entry | Add scope with registry URL |
| Authentication fails in CI | Token not passed via environment | Use ${VAR} syntax and set in CI secrets |
| Zero-Installs not working | enableGlobalCache: true | Set to false and commit .yarn/cache |
| Wrong Yarn version runs | yarnPath not set | Pin the binary in .yarnrc.yml |
Real-World Examples
1. Set Linker
nodeLinker: node-modules
2. Enable Local Cache
enableGlobalCache: false
3. Pin Yarn Version
yarnPath: .yarn/releases/yarn-4.5.1.cjs
4. Private Scope
npmScopes:
my-company:
npmRegistryServer: "https://npm.internal.example.com"
npmAuthToken: "${INTERNAL_NPM_TOKEN}"
5. Catalog
catalog:
react: ^19.0.0
typescript: ^5.5.0
6. Named Catalog
catalogs:
react18:
react: ^18.3.1
7. Workspace Profile
workspaceProfiles:
typescript:
devDependencies:
typescript: ^5.5.0
8. Disable Telemetry
enableTelemetry: false
9. Verify Config
yarn config
10. Commit the File
git add .yarnrc.yml && git commit -m "Configure Yarn"
Visual
.yarnrc.yml in the Project Structure
┌──────────────────────────────────────────────┐
│ project-root/ │
│ ├── .yarnrc.yml ← configuration │
│ ├── yarn.lock ← resolutions │
│ ├── package.json ← manifest │
│ ├── .yarn/ │
│ │ ├── cache/ ← local packages │
│ │ └── releases/ ← pinned Yarn │
│ └── .pnp.cjs ← PnP loader │
└──────────────────────────────────────────────┘
The .yarnrc.yml file controls how the other artifacts are generated.
Linker Decision
┌──────────────────────────────────────────────┐
│ nodeLinker: ? │
└──────────┬───────────────────────┬───────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ pnp │ │ node-modules │
│ │ │ │
│ .pnp.cjs │ │ node_modules/ │
│ No node_modules │ │ Filesystem walk │
│ Strict deps │ │ Universal tools │
│ Fast install │ │ Slower install │
└──────────────────────┘ └──────────────────────┘
The linker choice is the most consequential configuration decision.
Summary
| Item | Value |
|---|---|
| File name | .yarnrc.yml |
| Location | Repository root |
| Format | YAML |
| Linker setting | nodeLinker: pnp, node-modules, or pnpm |
| Cache setting | enableGlobalCache: false for Zero-Installs |
| Registry scoping | npmScopes |
| Secret injection | ${ENV_VAR} syntax |
| Shared versions | catalog: |
| Version pinning | yarnPath |
| Commit to Git | Yes |
Key takeaways:
.yarnrc.ymlis the single source of Yarn configuration. It replaces the fragmented.yarnrcand.npmrcapproach of Yarn Classic with one explicit YAML file .nodeLinkerdetermines the entire dependency model. PnP is the default in Yarn 4, butnode-modulesis required for compatibility with tools that assume filesystem resolution .- Registry scopes prevent dependency confusion. Private packages are routed to internal registries with
npmScopes, and authentication is injected from environment variables, never hardcoded . - Catalogs centralize version management. A single
catalog:entry in.yarnrc.ymlreplaces duplicated version ranges across every workspace’spackage.json. - TLS verification must remain enabled. Disabling
enableStrictSslexposes the package download to interception. Fix the proxy, not the SSL setting . - The file must be committed. Configuration drift between developers and CI is prevented only when
.yarnrc.ymlis version-controlled alongsideyarn.lock.
Remember: .yarnrc.yml is not a convenience file. It is the contract that defines how Yarn resolves, installs, and links packages in the project. Every setting has consequences—some for performance, some for security, some for the entire dependency model. Review changes to this file with the same scrutiny as changes to yarn.lock.
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!