Episode 5: Using Symlinks to Manage Monorepo Modules

In the previous lesson, we explored the Node Modules Trick, renaming the packages folder to node_modules to allow Node.js to treat modules as standalone packages. In this lesson, we’ll use symlinks (symbolic links) for a more elegant and professional solution to link modules within a monorepo.


A symlink (symbolic link) is like a shortcut to a file or directory:

  • It points to the original file or folder.

  • Any program accessing the symlink is redirected to the original location.

  • Supported on all major operating systems.

Both npm and yarn provide commands to create symlinks, allowing us to link packages seamlessly.


  1. Simulate installing packages from npm, even if they are local.

  2. Changes in the linked module are immediately reflected wherever it is used.

  3. Provides a clean and scalable monorepo structure.


Step-by-Step Guide: Creating a Symlinked Monorepo

Initial Directory Structure

Start with the following directory structure:

monorepo-project/
│
└── packages/
    ├── moduleA/
    │   └── index.js
    │   └── package.json
    └── moduleB/
        └── index.js
        └── package.json

1. Setting Up Module A and Module B

moduleB/package.json

{
  "name": "moduleB",
  "version": "1.0.0",
  "main": "index.js"
}

moduleB/index.js

console.log('This is module B');

moduleA/package.json

{
  "name": "moduleA",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "moduleB": "1.0.0"
  }
}

moduleA/index.js

console.log('This is module A');
require('moduleB');

2. Running Module A

Try running moduleA with the following command:

node packages/moduleA/index.js

Error:

Error: Cannot find module 'moduleB'

Node cannot resolve moduleB because it isn’t installed in the node_modules folder.


3. Linking Module B

Step 1: Register Module B Globally

Navigate to the moduleB directory and run:

cd packages/moduleB
yarn link

If using npm:

npm link

This command registers moduleB as a global symlinked package.


Navigate to the moduleA directory and run:

cd ../moduleA
yarn link moduleB

If using npm:

npm link moduleB

After linking, the following changes occur:

  1. A node_modules folder is created inside moduleA.

  2. Inside node_modules, a symlinked folder named moduleB appears.

  3. The symlink points to the original moduleB directory.

You can verify this in VS Code, where the symlink appears with a distinct arrow symbol.


5. Running Module A

Now, rerun moduleA:

node packages/moduleA/index.js

Output:

This is module A  
This is module B

  1. Real-Time Updates:

    • Any changes made to moduleB are instantly reflected in moduleA since the symlink acts as a pointer.
  2. Cleaner Workflow:

    • No need to rename directories or copy files manually.
  3. Scalable:

    • Works seamlessly as the monorepo grows.

Next Steps

In upcoming lessons, we’ll explore more robust tools like Yarn Workspaces and Nx to manage monorepos, which automate much of the symlinking process and provide additional features like dependency management and script orchestration.

By mastering symlinks, you’ve taken the first step toward managing monorepos effectively! 🚀