Let's rethink the way we share components to build our applications.
Today, frontEnd components in React, Vue and Angular let us compose applications through modular UI building blocks. A couple of years from now, framework-agnostic web components will take this to the next level.
Yet, up until 2018 the way we shared and reused modular components wasn't very different than the way we shared entire projects. If we wanted to share a component from one reposiotry to another, we would have to create a new reposiotry to host it, move the code there, boilerplate it as a package, publish it, and install it as a dependency in the new project.
That process is very hard to scale when it comes to smaller atomic components. It wasn't meant for components, it was meant for projects.
So, teams began to struggle with sharing components, trying to reduce the overhead around the process. This often led to the creation of projects called "shared component libraries" (example) which are basically a single project with many components.
But, in 2018 a new kind of sharing became possible: sharing components directly between projects, synced through a remote cloud-based collection. This was made possible thanks to a new open-source project called Bit, built for sharing smaller modules between larger projects.
In this post, we'll try to explore the question "Do I still need a component library?" and present the pros of cons of different component-sharing workflows. Let's dive in.
To better understand if a component library is the right choice, let's shortly review the pros and cons of building a component library. In short, the answer is: it depends :)
Instead of setting up 30 more repositories for 30 more components, you can just have 1 external repository to host all 30 components.
Consolidate the development of shared components into one project: PRs, Issues etc.
Assign a clear owner to the components.
Enforcement of stacks and standards (double-edged sword).
Basically, the main advantage of a component library depends on the perspective. Compared to a repo-per-component approach, it saves overhead and consolidates the development and consumption of components into one reposiotry and package. However, this can also be a downside. Let's review.
If the components are internal to your apps, it will require heavy refactoring to move them to the library.
Consumers just need a single component, yet they are forced to install a whole library. Lerna can help publish each component, but the overhead is heavy for many components.
How will you version and update individual components?
Discoverability for components is poor so you have to invest in docs-portals and maybe add tools like StoryBook or Codesandbox. Still, how can you search for a button component with X dependencies and only Y kb in bundle size? (see bit.dev below).
Component consumers can't make changes to the components without diving into the library and making a PR, then waiting for it to maybe get accepted. This often blocks the adoption of such libraries inside organizations. For many teams, this alone becomes a breaking point between the infra team building the library, and the app developers consuming it. Collaboration isn't good over the components.
You enforce styles and other things that don't fit any usecase for every consuming app, blocking the adoption of the library.
You make it hard to handle dependencies between components, as when you make a change to a component it's hard to tell which other components (in the library and otherwise) are affected and how.
You need to commit to additional tooling around the library to relife some of the pains (basic discoverability, individual publishing etc).
A component library can be compared to a music album CD-Rom (those of you over 25 will remember :). It's a static place you carry around with you, putting ~30 items on it. You have to read the cover to learn what's inside, and you can't search for songs. You also can't change the content without hard-burning the CD again. Over time, it takes some damage from ad-hock adjustments and starts to wear off. Collaboration across teams is very difficult with libraries, which often fail to get adopted at scale.
But, what if instead of a component CD album we can have a "component iTunes" - where we can easily share, discover, consume and update individual components from different projects? Keep reading.
In 2018 an open-source project called Bit was first introduced on GitHub.
Unlike the project-oriented tools we use for our projects (Git repos, package managers etc), Bit was built for atomic components.
bit.dev is Bit's component hub. Like GitHub, it's free for open-source too (and for some private code). Through bit.dev, components become available to discvoer, use and sync across projects and teams.
Let's quickly review.
When it comes to frontEnd components, Bit lets us automatically isolate components from a project (app or library) and wrap them in a contained environment that lets them run in other projects, out of the box. This environment contains all the files of the component, all its dependencies and the configuration it needs to build and run outside of the projects.
This means we can individually share multiple components from a given project in little time, with zero to very little refactoring.
Bit handles each component's versions and dependencies while extending Git to track changes to its source code, across projects.
Through bit.dev the components you share become discoverable to yourself and others to find, learn about and choose from.
You can semantically search for components by name, and filter results based on context-relevant labels, dependencies, bundle size and more useful parameters.
You can quickly browse through components with visual snapshots, and when you go into a component's page you can try it-hands on in a live playground before using it in your project. You can also view the API docs, automatically parsed from the code, to learn how it works.
Through bit.dev components are visualized so that developers, product, designers and other stakeholders can collaborate and have universal access to all the components within the organization.
Once you find a component you like, for example, shared by your team or the community, you can install it using package managers like npm and yarn.
Bit also lets you
bit import a component (or a whole collection) to a new project. This means Bit will bring the component's actual source-code into the repository, while tracking the changes you make.
You can then change something in the code, maybe a style for example, and tag the component with a new version. You can then share the new version back to the collection, and even pull the changes into any other reposiotry this component is written in, while leveraging Git to merge the changes between the versions.
Simply put, this means you can very quickly update a component right from your consuming app, so you don't have to dive into the library and wait on long PRs. While it requires some rules for collaboration (for example, choosing who can push new version into the collection in bit.dev), it also means people can adopt the components and fit them to their needs. Otherwise, the component might just not be used (or jusy copy-pasted and changes without anyone ever knowing about it :).
In this structure, the library functions as a development and staging area of the shared components. Bit and bit.dev are used to share the components, make them discoverable, and enable collaboration on top of the components to breed their adoption in the real world.
The best choice depends on your needs. For larger organizations with infra teams publishing components while other teams are consuming them, it's recommended to combine both- to develop all components owned by the infra team in their repo, and make all of them individually discoverable to find, use and -given simple regulation- update as needed.
For smaller teams of single developers trying to share a component between a couple of applications, a library might be an overkill and you can gust share components through your bit.dev collection- from one application to another, and keep them synced. You won't even need to refactor anything or add additional repositories to maintain.
Bottom line, it's really up to you :)