Build a truly modular component library that can be developed and used, one component at a time.
When you need to share common UI components (React, Vue, Angular, etc) between different projects or applications, you often build a shared UI library.
The main advantage of that is that you can group components together and avoid the tremendous overhead of multiple repositories. The problem is that they remain grouped when you develop, install and update them.
If you have an effective way to version, publish, install and update individual components, everyone’s life becomes much easier. You as the developer of the library have more freedom to develop each component and can control the dependency graph between the components developed in the library.
The people who install the library (yourself or other app developers) have the freedom to choose and consume only the components they really need, and get updated only for these components and not for the whole library.
Left: Grommet component library in GitHub; Right: Individual components published from the library.
In this post, we’ll learn how to use component-oriented tools like Bit to make this happen, without having to start refactoring your library. It will also provide other benefits for your library, such as component discoverability and the ability to organize shared collections for different teams/projects.
Why develop with individual components?
Development: You can leverage Bit to isolate each component as a standalone module in your library, including all its files and dependencies. You can version each component separately or together. As Bit lets you control the dependency graph for all the components in the project, you can develop each component and learn exactly how the changes you make affect other components in the repo, so you can update everything that needs updating. Then you can publish each component individually to be reused elsewhere.
Consumption: You and others can install each component individually using npm/yarn as a standalone package. When the consuming project requires changes, you can import any component’s source code right into that project to make changes. Then, you can just update and share a new version. This means working with a cross-reposiotry collaborative workflow as a team.
Updates: Consumers can get updates only for the components they use, without having to bring in updates for the whole library. They can also suggest updates to any component without diving into the library. This means more adoption for your library by the developers using the components.
Discoverability: You can create a shared bit.dev collection where all your components are available for everyone to discover, use and collaborate on. This even goes beyond just developers, as you can share components with other people like marketing, product, design, etc to learn what you have. You can render each component, play with examples, view auto-extracted API reference, run an isolated build/test process for every components and more.
Isolate, version and publish individual components from the library
Let’s use Bit to modularize the development and distribution of components in our library. It will do the heavy lifting for us and will grant us control over the exact state of each component’s dependency graph at any moment.
It’s a tool built for sharing components. Let’s use it to track different components in our library. It will analyze each of them, and pack it in an isolated capsule with all the component’s files and dependencies. Then we can version, publish and later update each component individually.
First, let’s quickly set up Bit for your library.
Install Bit and create a workspace for your library’s project:
$ npm install bit-bin -g
$ cd project-directory
$ bit init
Then head over to bit.dev and quickly create a free account. Then, create a collection to host your components (and to make them discoverable).
When done, authenticate bit to your bit.dev account:
$ bit login
Great! Now you’re all set to start tracking components. Use the bit add command to tell Bit where to find the components in your library.
For example, let’s track all the components in src/components. In this case, we’ll use a glob pattern to tell Bit to track all the components in this directory.
$ bit add src/components/*
Now run bit status and see that the components are tracked, and that bit didn’t miss a file or a dependency for any of the components.
Next, let’s import a compiler to built the code into files that can run in other projects too. For example, let’s use install a React compiler in the workspace:
$ bit import bit.envs/compilers/react
You can now run bit build to see that everything works fine.
Next, let’s set a version for the components. Bit will version each component with a minor version, but you can override and choose your own versions. Setting an independent version for each component is very useful for developing, publishing, installing and updating them individually.
For starters, let’s set all to v1.0.0. Later, we can use Bit to update individual components, while controlling the dependency relations between them.
$ bit tag --all 1.0.0
Next, run a quick bit status to
Now you’re ready to publish the components to bit.dev:
$ bit export <your-user-name>.<your-collection-name>
And that’s it! Now head over to your collection and explore the components. Each can now be added with a saved example, which bit.dev will render and present for the component. The examples will also help generate the snaphot preview bit.dev presents in the component collection, to help you choose.
For example, if you share the semantic-ui-react library you can turn this:
Into this collection of individually reusable components. Note that you can now even see the exact bundle-size and dependencies of each component.
And here’s an example of a component page where you can play with the code and see the component renders, and install the component using npm/yarn.
Next, let’s see how to install and later update individual components in different projects without having to pull in the entire library.
Install individual components from the library
When you enter a component’s page in bit.dev you can see that there’s a pane with different ways to consume the component. Let’s look at the transition component from semantic-ui-react:
transition - semantic-ui-react · Bit
*Callback on each transition that changes visibility to shown. Tags: React, Transition. Dependencies: classnames…*bit.dev
In the bit.dev page you can tell that it weighs only 73k and has a few dependencies including Lodash. It’s a bit much, but at least now I know exactly what I’m adding to my app before I actually install the component.
If you already run bit loginyou have your npm client configuered to bit.dev as a scoped registry. If not, run this following command to do so:
npm config set '@bit:registry' https://node.bit.dev
Then, just install the component using npm/yarn:
npm i @bit/semantic-org.semantic-ui-react.transition
# or
yarn add @bit/semantic-org.semantic-ui-react.transition
And that’s it. I only added the component to my app and didn’t have to install a whole library. Within your organization for example, this can help increase the adoption of the shared libraries you build and keep your apps fast & slim.
Update individual components in the library
When you make an update to a component in the library, you can just tag it again and then export it as a new version to your bit.dev collection. Before doing so you can even run bit status
to learn which other dependant components will be affected by the changes- and how.
Then, the consumer of the component can just bring in the updates for the components they actually use, without having to update the whole library.
Furthermore, the people consuming the components can use the bit import command to bring in the component’s actual source-code into any repo. There, they can locally make changes to the code, and tag a new version. The new version can stay local, or it can be shared back out to the collection. When exporting, you can pass the --eject flag to move the modified component back into being a package dependency in your package.json file.
The updated version can then be brought in to any other repo, including the original library. Since Bit uses Git under the hood, you can use Git’s merge utility to merge changes between different versions of your components in the same local Bit workspace, to easily sync code changes between repositories.
With an upcoming GitHub-sync integration, they can also use this workflow to issue a pull-request back to your library in GitHub. This can help with the adoption of your library and provide a collaborative workflow for everyone.
Component discovery and collaboration
Now that you’ve shared your library to bit.dev your collection becomes a shared portal through which your team can share reusable components.
You can search and explore components through a semantic search, filter relevant parameters like context-labels or component bundle-size, and let different people and teams collaborate over your shared components.
Example of a React Pacman loader component in the bit.dev editable playground
Library developers enjoy better control over the development and distribution of components in the library, and enhanced discoverability and collaboration over their components. Component consumers can just easily find and install components while getting and suggesting updates right from their projects.
This means you can build applications faster through modular components that be published, installed and updated across different projects. Hope this helps, so feel free to jump in and give it a try or explore the tutorials.** Cheers and please don’t hesitate to ask any questions below 👐
Top comments (1)
Excellent blog post. Thanks.