“Let’s make our components reusable!”

So lately I’ve been talking to many JS teams about how they reuse components. Here I’ll share some of what I learned… but first, a short intro.

The JavaScript landscape is shaping towards components. While modularity is here since the 60s, the JS ecosystem has never been so practical about it.

In the frontEnd, we see how component-based frameworks like React and Vue introduce newfound modularity into our UI development. Web components, with Stencil and Lit-HTML bring new promises of an even better future. At the same time, we’ve seen how microservices, GraphQL and Serverless functions bring better modularity across our architecture.

You probably have your own opinions on some of these names, yet the modular componentization across the stack is getting hard to ignore.

Modularity makes life better in many aspects. It helps us build focused pieces of software to compose a larger whole, encourages TDD, makes debugging easier with a separation of concerns and lets us extend rather than rewrite.

It also helps us write reusable code.

While everyone agrees that’s great, some feel that reusable code is often more of a pattern to aspire towards than a fully applicable practice. There are many reasons for this, from the R&D reality to tooling and team communication.

In this short post, we’ll explore how the componentization in the JS ecosystem make code reuse more practical than ever before, and try to set some key principles to help you make the right choice in the right moment. I hope you find it useful, and you are more than welcome to share your thoughts below.

Popular pitfalls

So let’s talk about why we don’t reuse more components.

I’ve spent the past months talking to hundreds of developers, team-leads, architects and open-source maintainers. I’ve asked them many things, including how does their team share and reuse code.

Not surprisingly, most of them tried to increase the usage of (reusable) components for different reasons from UI consistency through dev-velocity to code-sharing between back and front. Some even tried to create a component design system where developers can collaborate with designers.

There were a few common points which kept coming up as reasons why they don’t share as much code as they’d like to. Here’s the gist:

“Our code is not reusable enough” “All our components are in 1 app, where will we reuse them?” “It’s hard to publish/manage many reusable components” “We have a shared library but people don’t really use it” “We tried to encourage reuse but the concept lost priority”

I’ve had a long conversation with many of the people who voiced these issues. Many shared that they’d like to make their components reusable, and even attempted different initiatives (shared library, storybook) to some success.

Based on this research, I’ve put together some useful keys for understanding if and how you can increase the use of shared components in your team.

Reuse vs. Use

“would you couple your work to a library which you don’t develop? Will you explain to your PM/Wife/Husband that you’re still waiting on your pull-request to be accepted?”

So here’s something that will put a lot of sense into everything. Using something and reusing it are not the same thing.

Why is that important? because code is an evolving creature. We rarely write code that is abstract enough to be reusable everywhere. Code written in one place will probably need some modifications to be used in another. The developer is then faced with a dilemma, as code reuse will impair their ability to fit this code into the needs of the new project/feature. To use it, they need to modify it — now or in the future. This often leads to a quick copy-and-paste.

With this understanding, we know that component-reuse isn’t good enough if the reused code is limiting the developer from changing it. For this reason, many shared libraries remain un-adopted within the organization while infrastructure teams are trying to “enforce” or “encourage” their adoption. But, who wants to “reuse” code they can’t evolve?

So, let’s talk about using reusable code, and not just reusing code.

Writing fully reusable components?

Write an Eevee that can evolve and change as needed

Here’s a bold statement: not all components are reusable. However, most components are usable. Why? because they serve a defined purpose for the developer who wrote them. And that purpose is often needed elsewhere.

So, rather than writing “reusable components” you should try to write “useful components” which are good at serving their purpose. You should write them not to be reused out of the box, but to be abstract and composable enough to serve that purpose in a verity of implementations.

A common example can be a UI component with a certain styling choice (Inline CSS/CSS modules/Global CSS/CSS in JS etc). How will you reuse a UI component with built-in styling in a different app with a different design?

Don’t expect it to be “reused” as is. You can write a useful component with reusability in mind. Meaning, design the component so that it will be practical for you or another developer to adapt it for different styling requirements.

Either way, don’t expect your component to be reused out-of-the-box. Built it as a reusable template that can be modified for future usage. With the right tools, that makes all the difference. Many components meet this criterion.

The importance of tooling

FormidablelAbs/react-animations with Bit: choose and use

So, the rise of componentization gave birth to a verity of tools built to solve different problems around building modular software.

Bit is an incredible tool for sharing and managing components and small modules from development to production across apps. It’s build to make modularity a simple commodity.

IPFS issue #76: shared components with Bit

Lerna helps you manage and publish multiple NPM packages from one repository, known as a multi-package monorepo (not a monolith app).

StoryBook and similar tools help us visualize components and develop them with your own eyes.

The list is long and includes tools like Git submodules and more. Choosing the right tools of the job is the key to a successful experience.

While working on Bit, which is also an open-source project, I’ve learned it has a few key abilities with a unique potential for sharing (re-)usable components.

It makes it very easy (and fast) to publish 200 components from 1 repo or 10 repos, since it requires 0 refactoring to publish them all. This isn’t dark-magic; Bit isolates the components and their dependencies for you.

Visualizing them as a discoverable collection for everyone on the team.

In addition to installing components with NPM/Yarn, you can use Bit to develop them from any project they’re reused in- so you can make changes when needed and even sync (update+merge) them across projects/apps.

This way, you don’t need your components to be fully written for reusability in order to be reused, and it’s fast & easy to publish and manage them at scale.

Here’s a short 5-minute demo:

Architecture: Multi-repo vs. monorepo?

Should our architecture define the need for reusable components? In 9 cases out of 10, I’d say no(!). And here’s why:

When you work with multiple repos the same components are almost always needed in more than one repo. This is true for 2 different React applications, or for a React application that shares code with the backend. This is also true for UI components across apps, or for a common utility across microservices.

And here’s the twist: this is also true for 9 out of 10 “monorepos”. Why? because when we say “monorepo” we usually mean a “multi-package repo”. We rarely (if ever) talk of a Google-like monolith with a gazillion code-lines.

So when we have a multi-package monorepo, we also have other repositories — otherwise, we wouldn’t need to publish any packages in the first place. This is true even for teams of 10 developers, which can share code between their frontEnd web app, their mobile app, their backend etc.

This is also true for teams which have a shared component library, which is effectively a “component monorepo”, with Bit, Lerna or both.

So, unless you are Google, you can probably benefit from organizing and sharing some reusable components for your team in any architecture.

Which leads to… shared component libraries

Dan Abramov is right as usual

As most teams start to scale, they seek code-sharing and reuse in the form of shared libraries. Why? because they can maintain all these components in one place, have clear owners, and install them wherever needed.

But, shared component libraries are also tricky.

First, it’s not simple to develop and maintain 30 components in a repo, let alone 200 components. It’s not simple to publish them either. In addition, you will have to create a discovery portal for the components, like a docs portal or a visual component environment/collection. That requires some work.

Then comes the big challenge- getting your library adopted. First - why install a whole library when you just need a component? (and don’t go screaming “tree-shaking!!!” until you’ve benchmarked performance).

Second, would you couple your work to a library which you don’t develop? Will you explain to your PM/Wife/Husband that you’re waiting on your Pull-request to get accepted? that’s a serious setback.

Tools like Bit can help mitigate these problems and increase the adoption of your shared components, by making each component reusable as a standalone package (without the overhead) and by -given permissions- letting any developer develop the component’s source code right from any project.

Communication

Writing usable code, using the right tools to reuse it and even asking people to do so isn’t worth much unless you aspire to build better software.

Team communication is the key, just like it’s a key when 4 people are building castles with shared Lego pieces. We have to communicate. However, communication can take many forms: from words to pull-requests.

When we communicate over components, we collaborate. Having all our components available to discover as a collection is the first step. If you’re using Bit, this is part of the component-sharing workflow. If not, tools like Storybook can come in handy for this purpose.

React Material-UI as a shared Bit component collection

Then, you need to encourage adoption and collaboration over enforcement, to account for the needs of the developer and help them adopt the components. Code-sharing is as much of a mindset of communication as it as a solution.

Conclusion

This post was insufficient. Why? because it’s the tip of the iceberg when it comes to sharing reusable code in the world of components. However, I do hope it helped you think about how you can leverage components to grow modularity and code-sharing in a way that will speed your development, make it easier to develop new features, and make your life happier 😃

Don’t hesitate to find the time to think about your components and how to (re-)use them, as it will definitely pay off in the long run. In today’s JS ecosystem, it’s truer than ever before.