Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies

Balancing Flexibility and Consistency in Large CodebasesMonorepos have become an increasingly popular way to manage codebases, especially for organizations that maintain multiple projects with shared dependencies.However, one of the critical decisions …


This content originally appeared on Bits and Pieces - Medium and was authored by Eden Ella

Balancing Flexibility and Consistency in Large Codebases

Monorepos have become an increasingly popular way to manage codebases, especially for organizations that maintain multiple projects with shared dependencies.

However, one of the critical decisions to make when adopting a monorepo strategy is how to manage these shared dependencies. Two main approaches are the Single Version Policy and Independently Maintained Dependencies. Each has its advantages and challenges.

Independently Maintained Dependencies

The Independently Maintained Dependencies approach is often the default for those using tools like Yarn Workspaces or Lerna to manage their monorepos.

In this strategy, each project within the monorepo is responsible for managing its dependencies. Typically, this involves maintaining a separate package.json file for each project or a separate env.jsonc file for each development environment used by Bit components the belong to the same project.

One of the most apparent advantages of this approach is the flexibility it offers. Each project can use different versions of the same dependency without affecting other projects.

For example, suppose one project requires a newer version of React while another needs to stay on an older version for compatibility reasons. In that case, this approach allows both projects to coexist within the same monorepo.

However, this flexibility comes at a cost. The freedom to use different versions of dependencies can lead to significant challenges, particularly when projects within the monorepo need to share code.

If two projects use different versions of a shared dependency compatibility issues can result, that are difficult to diagnose and fix. Additionally, a common pitfall occurs when a developer inadvertently has one version of a dependency installed globally or in the root node_modules and a different version specified in the project’s package.json.

In many monorepo solutions, this discrepancy can lead to the dreaded “works on my machine” syndrome, where the application behaves differently in development and production environments.

However, tools like Bit help mitigate this issue by building components in environments isolated from the project and its shared node_modules directory (making sure that only those dependencies configured for a component or app component are available to be consumed).

Bit builds components in isolation to verify the right dependency versions are used

Single Version Policy

In contrast, the Single Version Policy approach enforces a uniform version of dependencies across all projects within the monorepo. This is typically achieved by maintaining a centralized package.json file at the root of the monorepo, where all dependencies are defined.

The most significant advantage of the Single Version Policy is the consistency it brings to the entire codebase. Ensuring that all projects use the same version of a dependency eliminates the compatibility issues that can arise when different versions are used. This uniformity makes it easier to share code between projects and reduces the likelihood of runtime bugs that are difficult to trace.

However, this approach has its challenges. Coordinating updates to dependencies becomes more complex, especially in large organizations where different teams may have other priorities and timelines.

Despite these challenges, the Single Version Policy can lead to more efficient and manageable codebases. Upgrading a dependency across the entire monorepo at once, while potentially disruptive, is often less time-consuming than performing multiple isolated upgrades over an extended period. When teams can collaborate effectively, the benefits of this approach, such as easier maintenance and reduced technical debt, far outweigh the drawbacks.

Finding the Right Balance

An ideal solution to this dilemma may lie in a hybrid approach that combines the best aspects of both strategies. Shared dependencies that are critical to the entire monorepo, such as React or TypeScript, could be managed centrally using the Single Version Policy. In contrast, less critical dependencies could be maintained independently by each project and updated to their latest versions when possible.

To implement this hybrid approach effectively, we need to establish clear guidelines and processes for managing dependencies within the monorepo, as well as the tooling to support these practices. Let’s see how this is done using Bit.

Bit. Composable software platform.

A centralized dependency management approach with Bit

Not all dependencies are created equal.

Peer dependencies, like React, are often shared across React projects in the same monorepo. They are part of the runtime environment of React components, which means they determine which components can be used together and how they should be used. Maintaining a single version ensures components can be shared and reused across projects without compatibility issues.

Dev dependencies like TypeScript, on the other hand, are part of the development standards and are often shared across the monorepo to maintain consistency.

Components maintained with Bit use reusable development environments that not only determine their tooling and build process but also their dependencies.

To ensure that all projects within the monorepo use the same version of a shared dependency, you can define it as a peer dependency in a reusable environment and apply it to all relevant components.

What if you have more than a single development environment? In that case, your dev environments can extend each other, allowing you to define the common dependencies in a base environment and add specific dependencies in the extended environments.

For instance, let’s look at our “React Env”. The React Env serves as a reusable development environment for React components and apps. It includes tools like TypeScript, Eslint and Webpack, as well as a build pipeline designed specifically for these components.

In addition to these tools, the env includes an env.jsonc file, which lists the dependency policy for components using it. This env can also inherit the dependency policies of another env used by the same organization for generic TypeScript components.

For example:

{
"extends": "@my-org/envs.typescript-env",
"policy": {
/**
* peer dependencies for components using that env.
*/
"peers": [
{
"name": "react",
"version": "^18.3.0",
/* the range of versions this env's components are compatible with */
"supportedRange": "^17.0.0 || ^18.0.0"
},
{
"name": "react-dom",
"version": "^18.3.0",
"supportedRange": "^17.0.0 || ^18.0.0"
}
}
}

Similarly, the “React Env” can be extended to create a more specific React development environment, designed for a specific product.

Development environments can extend other development environments

Component in a monorepo will use any one of these envs, according to their type and purpose. For example:

Bit components in a monorepo using different development environments

Updating shared dependencies with Bit: clear dependency graph, change propagation, and simulations

We often postpone updating shared dependencies because it’s a tedious and error-prone proccess.

Bit and the Bit Platform make it easier to update shared dependencies across the entire monorepo by providing a clear view of the dependencies used by each component and their versions.

Using a single command or a few clicks in the Bit UI, you can update a shared dependency across all components that use it, ensuring consistency and compatibility across the entire codebase.

In addition, Bit’s composable design allows a maintainer of a component to propagate the changes made to a component to all components that depend on it and are affected by it.

This can be actual new component releases for those components maintained by the team making the change, or a simulation that propagates to all dependents of the component, including those not owned by the team making the change.

Component changes are propagated to affected components owned by the same development team. Affected components owned by other teams will be built in a simulation to verify that an update can be done safely

Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Bits and Pieces - Medium and was authored by Eden Ella


Print Share Comment Cite Upload Translate Updates
APA

Eden Ella | Sciencx (2024-08-27T18:33:01+00:00) Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies. Retrieved from https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/

MLA
" » Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies." Eden Ella | Sciencx - Tuesday August 27, 2024, https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/
HARVARD
Eden Ella | Sciencx Tuesday August 27, 2024 » Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies., viewed ,<https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/>
VANCOUVER
Eden Ella | Sciencx - » Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/
CHICAGO
" » Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies." Eden Ella | Sciencx - Accessed . https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/
IEEE
" » Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies." Eden Ella | Sciencx [Online]. Available: https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/. [Accessed: ]
rf:citation
» Dependency Management in Monorepos: Single Version Policy vs. Independently Maintained Dependencies | Eden Ella | Sciencx | https://www.scien.cx/2024/08/27/dependency-management-in-monorepos-single-version-policy-vs-independently-maintained-dependencies/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.