Episode 7:Understanding Hoisting in Yarn Workspaces
What Is Hoisting?
Hoisting in Yarn Workspaces refers to the process of lifting dependencies from individual package directories to a shared node_modules
folder at the root of the repository.
This mechanism optimizes:
Dependency Management:
- Avoids duplicate installations for shared dependencies.
File System Structure:
- Simplifies the
node_modules
layout for better performance and disk usage.
- Simplifies the
Package Linking:
- Ensures packages are symlinked efficiently.
How Hoisting Works
Workspace Package Symlinks:
Symlinks for workspace packages (e.g.,
moduleA
andmoduleB
) are hoisted to the rootnode_modules
folder.This allows a single symlink per package, resolving dependencies globally.
Shared Dependencies:
Dependencies installed for one module but required by others are hoisted to the root
node_modules
.Example: Installing
lodash
for bothmoduleA
andmoduleB
results in one shared copy at the root.
Practical Example: Hoisting in Action
1. Checking Node Modules
In a typical Yarn Workspace setup:
moduleA/node_modules/
→ No folder present.moduleB/node_modules/
→ No folder present.root/node_modules/
→ Contains symlinks formoduleA
,moduleB
, and shared dependencies.
2. Installing Shared Dependencies
Step 1: Install lodash
in moduleA
Run:
yarn workspace moduleA add lodash
Check the root node_modules
:
lodash/
→ Installed here, shared globally.
Step 2: Install lodash
in moduleB
Run:
yarn workspace moduleB add lodash
Since lodash
is already hoisted to the root, no additional copy is created. Both moduleA
and moduleB
access the same instance.
3. Handling Version Conflicts
If two modules require different versions of the same dependency:
Root Version:
- The version required by one module (e.g.,
lodash@4.17.21
) is installed at the root.
- The version required by one module (e.g.,
Per-Module Version:
- The conflicting version (e.g.,
lodash@3.10.1
) is installed in thenode_modules
folder of the module that needs it.
- The conflicting version (e.g.,
Example:
root/node_modules/lodash/
→4.17.21
packages/moduleB/node_modules/lodash/
→3.10.1
Each module will resolve the correct version via Node’s module resolution algorithm.
No-Hoist Dependencies
When to Use nohoist
Some packages are not compatible with hoisting, such as:
React Native
Electron
Packages with binaries or non-JavaScript files that depend on specific locations.
Defining nohoist
You can specify packages that shouldn’t be hoisted in the root package.json
under the workspaces
property:
{
"workspaces": {
"packages": ["packages/*"],
"nohoist": [
"**/react-native",
"**/react-native/**"
]
}
}
Effect of nohoist
react-native
and its dependencies will be installed locally within each package’snode_modules
.These dependencies will not appear in the root
node_modules
.
Benefits of Hoisting
Efficiency:
- Reduces disk usage by avoiding duplicate installations.
Performance:
- Improves dependency resolution speed due to centralized management.
Flexibility:
- Handles version conflicts seamlessly when needed.
Compatibility:
- Allows opting out for specific packages via
nohoist
.
- Allows opting out for specific packages via
Summary
Hoisting centralizes shared dependencies at the root of a Yarn Workspace project, optimizing performance and disk usage.
Yarn resolves conflicts by installing specific versions in individual package directories when needed.
Use the
nohoist
option for packages that cannot or should not be hoisted.
Yarn Workspaces with hoisting provide a clean, efficient, and scalable solution for managing monorepos. 🎉