Visual Studio Code tips for monorepo development with Multi-root Workspaces and extensions
This is intended for developers working with Visual Studio Code in a monorepo. I’ve already mentioned this in part as a bonus in another post, but this one goes into a bit more detail.
Requirements
There is not much to do to make Visual Studio Code work in monorepos: by default, it should work out of the box, until you install extensions 😒. That’s not entirely true, but combined with a lack of configuration, your extension may not work well or at all. If you have problems with an extension and all configurations don’t work, try a multi-root workspace.
Multi-root Workspaces
A multi-root workspace is a feature in Visual Studio Code where you can have multiple root folders in one explorer view. This tells compatible extensions to use one folder within the required package, rather than multiple.
Multi-root workspaces contain settings that work on a global level and can be overwritten with another settings.json
inside its own project folder.
Multi-root workspaces can contain different folders, that means they can be from anywhere on a file system. In our monorepo case, we will only use the root
folder and the folders inside packages
. As an example, here we have a sample monorepo folder structure:
.vscode/
| project.code-workspace
packages/
| app1/
| | .vscode/
| | | settings.json
| | package.json
| app2/
| | .vscode/
| | | settings.json
| | package.json
package.json
You can see a .code-workspace
file for Visual Studio Code inside the root folder .vscode
. Note one thing: the paths in this file can be relative or absolute, and you can place it wherever you want to make it fit your repo. I like to bundle the workspace file into the root folder .vscode
because if someone uses a different editor or IDE, it will be placed where it belongs. As file name I use the project name, this is displayed in the window title of Visual Studio Code.
Here is an example of the contents of the project.code-workspace
file:
{
"folders": [
{
"name": "ROOT",
"path": "../"
},
{
"name": "packages/app1",
"path": "../packages/app1"
},
{
"name": "packages/app2",
"path": "../packages/app2"
}
],
"settings": {}
}
Let me explain this a little:
- folders: Displays the folders in the Explorer view as root folders. The order of these objects defines the order in the view.
- name: This key is optional and you can choose what you want
- path: The path to the folder you want to have as a root folder
- settings: Global settings for the workspace
Now our explorer view should look like this:
As you might have guessed, you can have multiple folders in the monorepo packages folder, but you don’t need to list them. This can help you structure only the things that you need to see and work on. If there is another app3
that is not in your responsibility, then hide it by not adding it in the folders list.
“But the other app folders are still shown by the packages in the root!” - Yes, you are right, so we change the workspace settings to “fix” this. Additionally we remove the node_modules
folder from view, since we don’t look in there most of the time.
{
"folders": [
{
"name": "ROOT",
"path": "../"
},
{
"name": "packages/app1",
"path": "../packages/app1"
},
{
"name": "packages/app2",
"path": "../packages/app2"
}
],
"settings": {
"files.exclude": {
"node_modules/": true,
"packages/": true
}
}
}
Let’s see what we have in the settings part of the file:
- files.exclude: Files or folders that should be excluded from the view and search function.
- node_modules/: Removes all node_module folders within the monorepo view
- packages/: Removes all packages folders within the monorepo view
Now your explorer view should look nice and clean:
Next, we will see how we can use some extensions to work in monorepos.
Extensions
Extensions are helpful for developers, and the Visual Studio Code marketplace offers a lot. Extensions can be installed directly from Visual Studio Code. For monorepo supported extensions, you can look at the multi-root ready and monorepo tagged lists. As mentioned in the first tag: they are compatible with multi-root workspaces.
Extensions installation
Launch Visual Studio Code Quick Open (Ctrl + P
), paste the following command, and press enter:
ext install orta.vscode-jest
Or use the internal extension sidebar in Visual Studio Code:
Read the official documentation on how to install and manage extensions.
Next, I’ll show you two of probably the most commonly used extensions for JavaScript development: Jest and ESLint.
Jest
The Jest extension has the “multi-root ready” support, but it may need some configuration for your monorepo. Before you install it , you should know a few things:
- Run each package with Jest package installed manually if possible. This conserves your computer resources.
- Disable workspace folders where you do not use Jest. The extension will try to search for Jest in the package and stops after some time with a console hint. Until then it takes your resources.
To prevent any strange behaviour, we add some settings to the project.code-workspace
file:
{
"folders": [
{
"name": "ROOT",
"path": "../"
},
{
"name": "packages/app1",
"path": "../packages/app1"
},
{
"name": "packages/app2",
"path": "../packages/app2"
}
],
"settings": {
"files.exclude": {
"node_modules/": true,
"packages/": true
},
"jest.autoEnable": false,
"jest.disabledWorkspaceFolders": ["ROOT", "packages/app1"]
}
}
Here we prevent the previously mentioned problems:
jest.autoEnable
: Jest is not executed automatically anywhere in the entire monorepojest.disabledWorkspaceFolders
: Disable Jest when running from theROOT
andapp1
folders, based on the folder names
Read more about troubleshooting here.
We can now control the start of the extension. One problem with the setting is that you can’t start the Jest: Start Runner
from Visual Studio code on app1
or ROOT
even if it is installed there. In my opinion, the combination of jest.autoEnable
and the Jest: Start Runner
command works well for most cases. You want to run Jest only when needed.
ESLint
If you mix different versions in the monorepo packages, then the ESLint Extension will use the correct version and show you linting errors based on its configuration. The best part is that you don’t have to configure anything in the .code-workspace
settings file.
Other extensions worth mentioning
Here is a small list of some other extensions that might be useful for you to try out if they can improve your development workflow:
- Monorepo Workspace: Easy way to hide and show monorepo packages in the explorer view
- Typescript MonoRepo Import Fixer: Useful for Lerna monorepos
Visual Studio Code recommendations
Let us recommend extensions for the workspace based on this page.
Create an extensions.json
file in the root .vscode
folder and add the following content:
{
"recommendations": ["dbaeumer.vscode-eslint", "orta.vscode-jest"]
}
This way, other developers will see a recommendation at the bottom of the extensions’ sidebar view.
You could insert it to the .code-workspace
file, too:
{
"folders": [
{
"name": "ROOT",
"path": "../"
},
{
"name": "packages/app1",
"path": "../packages/app1"
},
{
"name": "packages/app2",
"path": "../packages/app2"
}
],
"settings": {
"files.exclude": {
"node_modules/": true,
"packages/": true
},
"jest.autoEnable": false,
"jest.disabledWorkspaceFolders": ["ROOT", "packages/app1"]
},
"extensions": {
"recommendations": ["dbaeumer.vscode-eslint", "orta.vscode-jest"]
}
}
Now you need to check the extensions sidebar and filter for: @recommended
and check the Workplace Recommendations tab:
“Fun” notes:
- You can edit the file if you click on the pencil icon
- Visual Studio Code will open/edit the
extensions.json
file, not the.code-workspace
file ☹
Sum it up
Developing with Visual Studio Code in a monorepo is (IMHO) pleasant and you can structure the view in explorer easily. This allows you to remove a lot of unnecessary clutter from your eyes and focus on the important parts. The single .code-workspace
file is cleanly structured, so it is easy to integrate with other team members to have a template workspace in a project.
Most of the extensions need no configuration for a monorepo project. And if they do, most of the popular extensions have a hint in their documentation or description, so you should know what to do.
Remember, improving your workflow and workspace is also part of a development process.