Tutorial

Corralling Monorepos with Yarn Workspaces

Published on March 10, 2019
    Default avatar

    By joshtronic

    Corralling Monorepos with Yarn Workspaces

    While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

    Maybe not the most popular opinion, but I absolutely love monorepos. When you’re starting a brand new project, it just makes sense to have a single repo and growing things from there. Unfortunately, as projects grow, things can get unwieldy. Next thing you know, back and front end code are sharing dependencies and your package.json has grown to a few hundred lines! Never fear, yarn workspaces can help you tame the savage monorepo.

    What yarn workspaces brings to the table is an easy way to link your monorepos together, share dependencies and even pin different versions of the same dependency. It also allows you to quickly install dependencies for all of your subprojects with a single yarn install command.

    If you’re coming from a micro-services approach with multiple repositories, you’re probably already familiar with writing and dealing with scripts to bootstrap, connect and keep your repositories connected and in sync.

    yarn workspaces lets you do this out of the box so you can focus your time on things like actually coding!

    Getting Started

    Obviously to use yarn workspaces you will need to have yarn installed. If you don’t, please consult the yarn Installation Page and follow the directions for your particular system.

    If you’re working with an existing repository that you are using npm with, all you will need to do is run yarn in the repository. This will generate a yarn.lock file and get things in order for you to use yarn.

    For brand new projects, simply yarn init inside of your project directory and follow the prompts!

    To set things up for demonstration, I’ve created a brand new project called GatorFarm with a directory for front and back end code as follows:

    $ mkdir -p GatorFarm/{backend,frontend}
    $ cd GatorFarm
    $ yarn init # Proceed through the prompts
    

    Creating a Workspace

    For me, the beauty of a monorepo lies in the fact that everything is in one place. One repository to clone and you’ve got everything you need.

    As mentioned, this gets really hairy when you have a package.json that includes shared dependencies across multiple subprojects within your monorepo.

    This gets even hairier the moment you need to use a specific version of a package in one subproject but want or need to use a different version elsewhere.

    To help avoid these kinds of issues, we can treat individual subprojects as their own project, with their own dependencies. To do so, we need to run yarn init within each of the subdirectories we created earlier:

    $ cd backend
    $ yarn init # Proceed through the prompts
    $ cd ../frontend
    $ yarn init # And of course these prompts
    $ cd ..
    

    If you accepted the default values during yarn init, you will have a project named “backend” in the backend directory and a project named “frontend” in the frontend directory.

    The name field within your package.json is what yarn uses to to create a workspace. To actually create a workspace, we will need to edit the package.json file in the root of the GatorFarm project:

    $ vim package.json # Developer's choice of editor, obviously, Vim not required ;)
    

    And add a workspaces attribute, with an array of our subproject names. It should look something like this:

    {
      "name": "GatorFarm",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "private": true,
      "workspaces": [
        "backend",
        "frontend"
      ]
    }
    

    Note that the private attribute should also be present and set to true. Projects using workspaces are not meant to be published so if you didn’t specify this during yarn init you can do so now.

    Installing Dependencies

    Since we have a package.json in each of our subproject directories, we can add dependencies from the subdirectory for each project. Since we have a subproject for back and front end code, let’s add some of our usual suspects to the back end project:

    $ cd backend
    $ yarn add express uuid
    $ cd ..
    

    We can do the same thing in our frontend directory. We can even pin dependencies to different version numbers, for example, pinning the same uuid package we included in backend to an earlier version in frontend:

    $ cd frontend
    $ yarn add react uuid@^2
    $ cd ..
    

    If you were to try adding a dependency to the root of the workspace, you will be met with opposition from yarn. I’m not here to judge, so if you really want to add a dependency to the root of your workspace / project, you can do so with the -W/--ignore-workspace-root-check argument:

    $ yarn add lint-staged -W
    

    Linking Subprojects

    We’ve covered adding dependencies to our subprojects, but what about linking our subprojects together so that code can be reused?

    To link our subprojects, all you need to do is add the project’s name and version like you would any other dependency:

    $ cd backend
    $ yarn add frontend@1.0.0
    

    Be warned if you omit the version number, you run the risk of including an external dependency from NPM instead of our local subproject.

    It’s also worth noting that generic names like frontend and backend can exasperate this overlap with npm packages, so it may be worth it for you to come up with less generic naming conventions :P

    A Fresh Start

    We now have a project with two subprojects that’s configured as a yarn workspace. Since we walked through each step to get things up and running, you didn’t get to experience one of the best parts of workspaces, installing all of your project and subprojects dependencies with a single command!

    You’re welcome to commit and push your changes and then clone a new copy of your repository if you’d like, or you can just clear out the node_modules directories from the root of the project and each of your subprojects.

    Once you have a clean copy of your project, simply run yarn install from the project’s root and bask in the glory of all of your dependencies being installed, across multiple subprojects, with one command! 💪

    Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

    Learn more about us


    About the authors
    Default avatar
    joshtronic

    author

    Still looking for an answer?

    Ask a questionSearch for more help

    Was this helpful?
     
    1 Comments
    

    This textbox defaults to using Markdown to format your answer.

    You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

    I have issue in the “Linking Subprojects” part. Yarn tries to search the package from registery, rather than using local.

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Get our biweekly newsletter

    Sign up for Infrastructure as a Newsletter.

    Hollie's Hub for Good

    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

    Become a contributor

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    Welcome to the developer cloud

    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

    Learn more
    DigitalOcean Cloud Control Panel