Contents
Outline
In this blog post, I will introduce how to set up a monorepo using Yarn
’s Workspaces
.
Blog Series
This blog is a series. Please check other blog posts through the following links.
- [Project Management] Repository Strategy
- [JavaScript] Tools for Monorepo
- [Monorepo] Node JS module resolution
- [Monorepo] Symlink
- [Monoepo] Yarn Workspaces
- [Monoepo] Dependency Hoisting of Yarn Workspaces
- [Monoepo] Command of Yarn Workspaces
- [Monoepo] Creating a Monorepo with PnpM
Yarn Workspaces
In the previous blog post(Tools for Monorepo
), I introduced Yarn
’s Workspaces
.
In this blog post, I will introduce how to set up a monorepo using Yarn
’s Workspaces
.
- Office document: Workspaces
Yarn
’s Workspaces
is a feature that allows you to manage multiple projects in a single codebase using the Symlink
introduced in the previous blog post. This feature makes it easy to set up a monorepo.
Example
Let’s create an example to check the Workspace
feature provided by yarn
. First, create a folder and file structure as follows.
.
└── 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 configuring the files like this, run the following command to check if the module is loaded correctly.
node src/module-a/index.js
After running the command, 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' ]
}
Yarn Workspaces Setup
Now let’s use Yarn
’s Workspaces
to make module-a
use module-b
. First, run the following command in the root folder(/
) to prepare to use Yarn
’s Workspaces
.
yarn init -y
After that, the following package.json
will be created in the root folder.
{
"name": "monorepo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT"
}
In order to use Yarn
’s Workspaces
, you need to modify this package.json
file as follows.
{
"name": "monorepo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"workspaces": {
"packages": ["src/module-a", "src/module-b"]
}
}
Monorepo has multiple projects, so it is not necessary to deploy to places like the npm
registry. Therefore, set private
to true
to prevent the monorepo from being deployed. Yarn V1
requires this setting, but Yarn V2
does not require it. It is recommended to set private
to true
to manage it safely. Of course, individual projects in the monorepo do not need to set private
because they can be deployed.
Workspaces
can be set as an array([]
) or an object({}
). Yarn
recommends writing it in object format. In Workspaces
, an array is created with the key packages
and each module is added. You can specify each one like this, but you can also specify all modules simply by using *
as follows.
{
"name": "monorepo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"workspaces": {
"packages": ["src/*"]
}
}
Check Yarn Workspaces
We are now ready to use Yarn
’s Workspaces
. Now run the following command to install the packages.
yarn install
Then you can see that the node_modules
folder is created in the root folder and each module is connected via Symlink
.
.
├── node_modules
│ ├── module-a -> ../src/module-a
│ └── module-b -> ../src/module-b
├── package.json
├── src
│ ├── module-a
│ │ ├── index.js
│ │ └── package.json
│ └── module-b
│ ├── index.js
│ └── package.json
└── yarn.lock
Now let’s check if module-a
can use module-b
by running the following command.
node src/module-a/index.js
Then you can see that module-a
is executed without any problems.
module-a
module-b
Of course, since it is connected via Symlink
, if you modify the code of module-b
, you can use the modified code in module-a
. Open the src/module-b/index.js
file and modify it as follows.
console.log('module-b!!!');
Then run the following command to check if module-a
works correctly.
node src/module-a/index.js
After running the command, you can see that the modified content is displayed correctly.
module-a
module-b!!!
.gitignore
If you are managing the source code with Git
, create a .gitignore
file and modify it as follows to exclude the node_modules
folder from Git
.
# .gitignore
node_modules
Completed
Done! We’ve seen how to use Yarn
’s Workspaces
to set up a monorepo. Yarn
’s Workspaces
basically works with Symlink
, so it’s good to understand Symlink
. If you want to know more about Symlink
, please see to the previous blog post.
Now you can try using Yarn
’s Workspaces
to set up a monorepo.
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku
.Deku
created the applications with Flutter.If you have interested, please try to download them for free.