6 Ways to Share and Reuse React Components
Share React components between projects in a managed way to keep your codebase DRY and maintainable.
The DRY principle is as basic as it gets. Still, in most codebases, you can find thousands if not hundreds of thousands of duplicated code-lines.
Code duplications are bad. Really bad. Why? Well, if you copy-paste code you make future maintenance a nightmare. If you rewrite code, you do the same thing, only you spend more time doing it.
Instead, you can -and should- aim to share as much reusable code as possible in a managed way. In modern development workflows, with tools like Bit and friends, you can scale the reuse of small modules/components to hundreds and thousands of units without too much overhead.
In this back-to-basics post, I’m listing a bunch of useful ways to share modular and reusable code. Feel free to add your own in the comments. Cheers.
1. Bit + Bit.dev
Bit is probably the most scalable way to share reusable JS code in a managed way. While built for UI components, it works with most kinds of JS code files.
With Bit you can scale shared code in a managed way to hundreds of reusable components with relatively very little effort or overhead.
Bit’s CLI tool (GitHub) lets you quickly isolate, package, version and publish reusable code to bit.dev — and the best part is, it can be done from any existing project. It abstracts away the setup of dependencies, configurations, etc — so that your components can be reused in other projects. It then lets you quickly consume, update and manage reusable components across projects.
The Bit.dev platform is where you can host, find and reuse all your reusable components. As you share more components to your collection, you grow your reusable toolbox of common code units. Each can be installed or forked right into any new project so you can use and even edit it right away. Since every component is versioned, you can send and get updates for each component.
Put together, you get the end-to-end managed experience for sharing reusable code components across your team’s projects at scale.
Try it or learn more here:
2. Multiple packages
In the past, your common option would be to keep a new Git repo for every piece of code you want to reuse and then publish it as a versioned package.
While this lets you individually version and update each reusable components, this also means quite a lot of overhead, as you’d quickly find yourself setting up and maintaining dozens or hundreds of repositories. Ouch.
3. A Single library package for many components
Anoher option is to put a few dozen shared components in a single repository and publish this “shared / common library” as a single versioned package.
The upside is that you reduce the setup of the library to a single repository and can maintain all the common code in one repository. However, there are a few serious downsides too:
- All shared components will be single-versioned. No independent updates, no version mix and match. Every project using this library will have to introduce every update to the library, relevant or not.
- You add quite a lot of redundant code and weight into your apps.
- It’s hard to PR changes into the library.
- You couple different projects to the library. In a microservice architecture for example, you really don’t want to do that (with Bit, for example, you can fork and control every module in any service, and still get updates).
- This solution doesn’t scale well and usually halts at a few dozen units.
Note that thanks to tools like Bit and Lerna you can version and publish multiple modules from one repository. Lerna is slimmer than Bit and does not provide many of its capabilities, but handles larger packages well with automation for versioning and publishing. If sharing many smaller components Bit might be a better choice thanks to its powers of abstraction, control, and scalability at sharing components (multi-component repo).
4. Git Submodules & friends
Git Submodules allow you to keep a Git repository as a subdirectory of another Git repository. In theory, this lets you clone another repository into your project and keep your commits separate. Why is that useful? because it lets you use another project from within the project you’re working on.
However, if you run a quick Google search for Git submodules, the results will not be positive. This is because of some major drawbacks around git submodules, such as being locked to a specific version of the outer repo, the lacking of effective merge management, and the general notion that the Git repository itself doesn’t really know it’s now a multi-module repository.
Git, at its base, also isn’t built to handle dependencies and relationships between components. The workflow around code-sharing, therefore, becomes complicated, and Submodules are struggling to deliver our desired workflow. In mercurial, subrepositories are named “feature of last resort” to be avoided.
There are also other alternatives to check out:
5. Go full-blown monorepo
Well, another option to solve the common code sharing problem is to cancel it. How? by placing all different projects and apps in one repository.
Is that useful? well, I wouldn’t recommend this type or architecture just to share code. Going full-blown monorepo has some other advantages too, for example consolidating different workflows and communications.
But whilemono-repo has multiple benefits, it also has some drawbacks:
- Established in an existing environment — if a project is starting from the ground up, building a single mono-repo can be the right solution. However, integrating this process into an existing infrastructure may require a large investment which is not always possible.
- Mono-repos require strong tooling to let it work as a set of single repositories. While some larger companies such as Google use such tools, not every organization has the capacity to introduce those changes. You can read more here.
- Mono-repos make it hard to secure parts of the code. In some scenarios, it is not desirable for everyone to be able to change any piece of code. Also, it is impossible to let only certain people, such as external contractors or collaborators view all of the code. It’s also hard to open-source parts of it.
Who does this in real life? Google. Take a look at this 30 mins mind-blowing talk below. Keep in mind they’ve put hundreds of millions into tooling just to make that possible. Is that the right scalable choice for you? It’s your decision to make. Just keep in mind that this is a commitment you’ll stick with.
Note that tools like Bit can serve as a “virtual monorepo” to manage shared code -both code changes and dependencies- across different repositories.
6. Copy-pasting code (don’t…)
Don’t copy-paste components. This later makes maintance a nightmare. It’s not worth it. Seriously.
You can copy-paste code. Well, assuming you also somehow copy-paste and fix all required dependencies, configurations etc. This isn’t always as quick as you think. But never mind that, what happens after you’ve copy-pasted code in 6 different repos and now you need to update something? It’s strongly recommended to manage common code and not copy-paste it.
I’ve talked to teams that reduced over 150K (!) code lines from their codebase by managing as few as 30 shared components/modules. Try to translate this number into accumulative human hours of working to find and fix every change in all these different instances of the duplicated code. Yeah, good luck with that. So be kind to future you and your friends, and please don’t.