[Monoepo] Symlink

2024-01-23 hit count image

Let's see what Symlink (Symbolic Link) is, which is the basic knowledge for using Monorepo in a project developed in JavaScript.

Outline

When connecting the dependencies of various modules in Monorepo, Symlink is used. In this blog post, I will explain Symlink (Symbolic Link), which is the basic knowledge for understanding Monorepo.

Blog Series

이 블로그는 시리즈로 제작되었습니다. 다음 링크를 통해 다른 블로그 포스트도 확인해 보시기 바랍니다.

Symlink is an abbreviation for Symbolic Link, and you can think of it as a shortcut (System shortcut) for a file or directory.

Symlink is a basic feature supported by major OS (macOS, Windows, Linux). In addition, it is also supported by npm and yarn, which are package managers for JavaScript.

Example

Let’s create an example to check the Symlink feature provided by npm and yarn. First, create the following folder and file structure.

.
└── src/
    ├── module-a/
    │   ├── index.js
    │   └── package.json
    └── module-b/
        ├── index.js
        └── package.json

The package.json of module-a is as follows.

// src/module-a/package.json
{
  "name": "module-a",
  "version": "1.0.0",
  "main": "index.js"
}

The package.json of module-b is as follows.

// src/module-b/package.json
{
  "name": "module-b",
  "version": "1.0.0",
  "main": "index.js"
}

And the index.js of module-b is as follows.

// src/module-b/index.js
console.log('module-b');

Finally, the index.js of module-a is as follows.

// src/module-a/index.js
console.log('module-a');

require('module-b');

After creating the file structure like this, run the following command to check if the module is imported well.

node src/module-a/index.js

Then, you can see the following error.

module-a
node:internal/modules/cjs/loader:1073
  throw err;
  ^

Error: Cannot find module 'module-b'
Require stack:
- /Users/deku/temp/temp/src/module-a/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1070:15)
    at Module._load (node:internal/modules/cjs/loader:923:27)
    at Module.require (node:internal/modules/cjs/loader:1137:19)
    at require (node:internal/modules/helpers:121:18)
    at Object.<anonymous> (/Users/deku/temp/temp/src/module-a/index.js:3:1)
    at Module._compile (node:internal/modules/cjs/loader:1255:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/Users/deku/temp/temp/src/module-a/index.js' ]
}

Now, let’s create a Symlink to check the Symlink feature. First, go to the module-b folder.

cd src/module-b

After then, run the following command to prepare to use Symlink.

npm link
# yarn link

Then, go to the module-a folder that uses module-b.

cd ..
cd module-a

After then, run the following command to create a Symlink for module-b.

npm link module-b

Then, you can see that the node_modules folder of the module-a folder is created as follows, and the Symlink of module-b is created in it.

.
├── index.js
├── node_modules
│   └── module-b -> ../../module-b
└── package.json

This Symlink folder is not a copy of module-b, but is linked to module-b itself. Therefore, if you modify the src/module-b/index.js file, the src/module-a/node_modules/module-b/index.js file will also be modified. Of course, if you modify the src/module-a/node_modules/module-b/index.js file, the src/module-b/index.js file will also be modified.

Now, go to the root folder (/) of the project and run the following command to check if the module is imported well.

# cd ../..
node src/module-a/index.js

Then, you can see the following output without any problems.

module-a
module-b

Next, let’s modify the src/module-b/index.js file as follows.

console.log('module-b!!!!');

Then, when you open the src/module-a/node_modules/module-b/index.js file, you can see that the modified content is reflected. Of course, if you run the following command, you can see that the modified content is shown well.

node src/module-a/index.js

module-a
module-b!!!!

Completed

Done! We’ve seem what Symlink is, which is the basic knowledge for using Monorepo. When connecting the dependencies of various modules in Monorepo, Symlink is used. Therefore, if you understand Symlink in here, it will be helpful to use Monorepo.

Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!

App promotion

You can use the applications that are created by this blog writer Deku.
Deku created the applications with Flutter.

If you have interested, please try to download them for free.

Posts