DEV Community

Cover image for 5 Practical Ways To Share Code: From NPM To Lerna, Git Submodules and Bit
Eden Ella
Eden Ella

Posted on • Originally published at Medium

5 Practical Ways To Share Code: From NPM To Lerna, Git Submodules and Bit

Between multiple repositories, monorepos and micro-services the discussion about sharing common code between projects is increasingly raging.

Sharing common code between projects and repositories is a key factor for better modularity and faster development, but it’s also complicated. I’ve written about it before, sharing from our own experience as a team.

Here is a practical overview of 5 methods for sharing code between these repos and projects for 2018. Just remember, down the line it’s really all about communication between people, culture and keeping modularity in mind.

1. Bit

Bit (GitHub) is a popular JS tool that manages both source-code changes and dependencies for shared components. It’s a powerful way to share code as a team, and keep it synced across different apps and projects.

Bit’s ability to isolate and share code from any repo to another, while maintaining universal control over changes and updates, makes it a very scalable way to increase code-sharing as a team, and reduce overhead.

Bit lets you seamlessly isolate and share modules from any repo, while it wil automatically define their environments and dependency tree. The result is almost instant publishing of components from any repo, with 0 refactoring.

UI components as Bit modules: instantly share and reuse anywhereUI components as Bit modules: instantly share and reuse anywhere

Then, you can install components in other projects with NPM/Yarn, or use Bit to import and develop the code right from the consuming project itself. When changes are made, Bit helps you update the versions and merge the changes.

It’s an open source project and a component-platform which together helps teams turn reusable code units into shared-components.

Bit’s platform (bit.dev) also provides discoverability and collaboration over the components you share, which are organized in visual collections in the platform with per-component testing, build, visual rendering and more.

Here is an example React project and a matching collection of components.


Share reusable code components as a team · Bit
*Easily share reusable components between projects and applications to build faster as a team. Collaborate to develop…*bit.dev

teambit/bit
*Easily share code between projects with your team. - teambit/bit*github.com

2. NPM with / without Lerna

Sindre Sorhus with 1000 NPM packagesSindre Sorhus with 1000 NPM packages

NPM is an amazing thing that happened to JavaScript, opening the door for code reuse and collaboration around reusable modules and libraries. With all the complaints about this ecosystem, we couldn’t imagine life without it.

As you probably know all about NPM, let’s focus on a few limitations and how to overcome them. Making smart choices from the get-go saves time later.

[Dan Abramov](undefined) favors many modulesDan Abramov favors many modules

First, it can be hard to setup and maintain many repositories for many packages. For this reason, some projects are built as multi-package repositories, also known as “monorepos”. Tools like Bit and Lerna (see below) can help you turn projects into multi-package repos, you can learn more here.

This also leads many teams to choose shared-libraries as a solution for sharing many smaller components (see below), as it’s hard to have a package for each.

Second, when someone else publishes a package you are limited in your ability to develop it, often leading to a pull-request to the packages’ repo. Tools like Bit help mitigate this problem, as it lets you bring the component right into any repo, make changes and share a new version.

Third, there is a discoverability problem as you scale. It’s hard to find and choose from many small packages, which leads to wiki sites and long docs. Rollup’s author Rich Harris wrote:

“Many blog posts — scratch that, entire websites — have been created to try and mitigate the difficulty of finding what you need on npm…”
“*It’s up to you to evaluate the library: does it have tests? Can you understand the source code? Is it actively maintained? Is the documentation easy to find and consult?”*

Lerna

The Hydra from Lerna: Looking at its tail, I think it’s about to fall downThe Hydra from Lerna: Looking at its tail, I think it’s about to fall down

Keeping different packages in different repositories can quickly get out of hand and make it very hard to update changes across your projects.

**Lerna** helps you to keep and configure multiple packages in a single repository. It can help mitigate the pain of different repos for different packages, and help build and test the project as a whole. This way, you don’t have to keep and maintain separate repos for different packages.

To learn more about going monorepo check this out:
*Monorepos Made Simpler *
*How to leverage Bit + NPM to simplify monorepo architecture, with and without Lerna and friends.*blog.bitsrc.io

3. Shared and common libraries

The advantage of shared-libs is that you keep all your shared code in one repo, which is easier to maintain and distribute than multiple micro-packages. However, unlike Lerna monorepos, they will be consumed as one package.

Keeping all your shared code in one repo forces users to add the entire library to their project with redundant code, dependencies, complexity and weight, all to use a single component.

A React MaterialUI button component — do I really need a whole library?A React MaterialUI button component — do I really need a whole library?

It also makes the process of updates and modification very cumbersome, as every change requires the owner of the project to update the package. This can impair the adoption of these libraries within the organization. Discoverability for different components within the library is also an issue.

These problems led communities such as Lodash to work long and hard in order to publish their components as individual packages to NPM. Google’s Polymer project (by Eric Bidelman and other OSS wizards) also keeps over 100 web elements in over different 100 repositories.

Lerna can be used to separate components within the library into packages within the repo. Bit can be used to share components from existing libraries.
How Do We Really Use Reusable Components?
*I’ve talked to 30 teams about their reusable components. Here’s what I’ve learned.*blog.bitsrc.io

Shared Components Best Practices for 2019
*Successful practices for developing and managing shared components between teams and projects with Bit and friends.*blog.bitsrc.io

4. Git sub-modules

Lessons learned in the trenches?Lessons learned in the trenches?

Submodules are effectively separate repositories within the directory tree of their parent repository. The only linkage between the parent and the submodule is the recorded value of the submodule checked-out SHA, which is stored in the parent’s commits. Changes in that recorded SHA are not automatically reflected in the submodules.

However, submodules have many, many problems. Just run a quick “git submodules” search on Google, and you won’t like the results. Among the major issues, you can find the simple fact that submodules don’t manage the dependency relationships between the modules. Smaller issues include issues like the fact that** **git submodule doesn’t work well with that parent, because a pull to the parent directory doesn’t automatically reflect in the submodule.

Also, git doesn’t save the pointer to the submodule when resolving conflicts. This means that if you don’t update the pointer manually you will lose resolved conflicts when merging changes. When you commit to submodule, git will leave you with a detached head in the parent because it is referring to an old “head” which is different from the current “head”. and guess what? When you push parent or submodules other parents don’t get exported.

There are various tools that provide additional automation around the Submodule feature, such as git-subtree, gitslave, braid and giternal. But as of today, the only tools that manage both source-code changes and dependencies for modules across projects and repos is Bit, in JS.

5. Copy-pasting code

Because let’s face it, what did future me ever do for me?

When your teammate yells YOLO and goes rougeWhen your teammate yells YOLO and goes rouge

To be honest, it is perhaps the most commonly used practice for code “reuse” on earth. I’d like to think that in most cases it’s the result of the lack of a “cheap” effective alternative and somewhat chaotic delivery cycles.

The problem is, code duplications are not cheap at all. Far from it.

A classic problem for future me.A classic problem for future me.

Duplications are an ever-growing debt in your code base. You will quickly lose control, making maintenance a nightmare and delivery cycles ever longer. Many problems will only be discovered after delivered to production.

A recent study found that half the code on GitHub is duplicated. Our research found that a Javascript function like is-string was duplicated over 1,000 duplications of 100 different implementations in only 10k GitHub repos.

Think about the new features that could have been written if more people would share code, rather than duplicate or reimplement it. Think about the costs of maintenance and long delivery cycles for your organization.

Sharing code is about people

Each project and every developer has their own set of concerns, tools and workflows. Still, sharing code is the key to true modularity, which becomes increasingly popular in todays’s ecosystem and provides great advantages.

We chose to build Bit. No matter what method and tooling you choose, it’s important to encourage a culture that breeds sharing and collaboration.

After all, sharing between projects starts with sharing between people.

Top comments (2)

Collapse
 
msm8 profile image
John Brooks

Does Bit support only UI components? and if so, which frameworks?

Collapse
 
giteden profile image
Eden Ella

Bit supports exporting and sharing UI components (React, Angular, Vue) but also Nodejs/JS/Typescript functions (utility, etc.)