Why I Publish and Manage Shared JavaScript Code with Bit

By Chidume Nnamdi 🔥💻🎵🎮

NPM has traditionally been an online registry for sharing code from snippets, components to full frameworks (Angular, React, etc). While it has it faults, I use NPM every day.

It helps us create a package for a library and push it to NPM’s online database so whenever we feel the need in our project to use the same functiononalities we can install the package from NPM.

Let’s say we are in a team to build an exchange app. The app comprises of many levels of components. Our folder structure will be organized like this:

exchg_app
- node_modules/
- src/
- Delivery-Page.js
- Delivery-List.js
- App.js
- index.js
- package.json

The Delivery-Page.js page will render the Delivery-List.js page which will contain a list of deliveries ordered by customers. Now let us imagine that we need the Delivery-List.js as an independent component to be reusable across several projects. How do we do that?

We create a new repo shared-compos that contains Delivery-List.js and its dependencies:

shared_compos
- node_modules/
- src/
- Delivery-List.js
- index.js
- package.json
- rollup.config.js
- .gitignore
- .npmignore
- .babelrc

Now, we npm publish shared_compos to NPM and install it in our project when we want to make use of the Delivery-List in any project.

npm i shared_compos
react-prj
- node_modules/
- shared_compos/
- dist/
- delivery-list.min.js
- package.json
...
- src/
- Display.js
- index.js
- App.js
- App.css
- index.css
- package.json
- .gitignore
{
...
dependencies: {
shared_compos: "^0.01"
...
}
}

We published the shared_cmpos to NPM and installed it in react-prj project. With this, we can use the Delivery-List component in react-prj.

Did you notice anything in this approach?

  1. If this function is written in a larger repo, we’d have to refactor the repo in order to separate it and create the right configurations and environments.
  2. For any changes in the Delivery-List in shared_compos, we will need to republish the package and reinstall it in react-prj. This often means coupling our app’s development to a 3rd party library.
  3. Version clash, one version of a package module may clash with the previous version and deprecations of methods and functions will seriously affect workflow and development.
  4. We increase in app size because of additional files in the shared_compos library: package.json, node_modules/,dist/.

While NPM is great for libraries, it might be cumbersome for sharing and reusing smaller modules and components. Especially if they’re written in a larger project. This is true from publishing to development across the board.

In this post, I’ll show how using Bit I can do things differently. I can choose a function from a project and instantly make it reusable in other projects. Moreover, I can continue to develop it from any other project too.

Bit will automate and handle everything for me, from versioning the small package to automatically resolving all its dependencies. This isn’t black magic, and you can learn more about it here. The result is a blazing-fast and minimum effort workflow for sharing reusable code across projects.

GitHub discussion re Bit’s experience

Bit solves all the risk and overhead points we traditionally face with NPM, which was built to share larger libraries as packages.

Bit gives us the ability to:

  • Instantly “isolate” functions or components as reusable modules right from any repo structure and environment — without any refactoring.
  • Reduce to 0 the effort of managing dependencies and versions for the code we share.
  • Install in in any other project with NPM and Yarn.
  • Use Bit to develop the code right from any consuming project, so that changing the package becomes a matter of seconds.

Lerna came in with a solution to create monorepos and symlink the monorepos without forcing to publish to NPM. Very good, but the thing is that it still allows the creation of monorepos, that is an extra Node project. Bit allows us to share components or utilities without any extra creation of project folders or configurations. This sounds like a lot, but it’s quite simple.

The to-be-reused components/utils are shared directly from its existing project without refactoring anything.

Let’s demo with the exchg_app project:

exchg_app
- node_modules/
- src/
- Delivery-Page.js
- Delivery-List.js
- App.js
- index.js
- package.json

We can share the Delivery-List.js component from this folder directly without creating another project for it or refactoring anything. All we need is to install bit globally:

npm i bit-bin -g

Initialize Bit workspace in the project:

cd project directory
bit init

Now we track the Delivery-List.js component:

bit add src/Delivery-List.js

At this point, Bit will automatically identofy and resolve all the function’s dependencies: packages, other files etc.. and create an isolated component.

Next, let’s use bit tag to lock a version for the component.

bit tag -a 1.0.0

Create a Bit account at bit.dev and create a collection. Now export the Delivery-List to your collection:

bit export <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>

Now if we want to use the component in the react-prj project, we simply import the component like this right from Bit’s hub

bit import <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>/Delivery-List --path src

NB: It’s also possible to use your favorite package manager NPM or yarn to install the components you publish with Bit!

The react-prj will look like this:

react-prj
- node_modules/
...
- src/
- components/
- Delivery-List.js
- Display.js
- index.js
- App.js
- App.css
- index.css
- package.json
- .gitignore

See, No additional insertion in node_modules complexity. The file(component/util) is only added to the project.

Let’s say you have a component NPM library already published in the NPM registry like our shared_compos which contains the Delivery-List component.

You can do away with the library and publish the Delivery-List component solely to Bit registry. So you can import the component directly without additional files and bloat to the node_module(through dependencies).

We have the shared_compos project:

shared_compos
- node_modules/
- src/
- Delivery-List.js
- index.js
- package.json
- rollup.config.js
- .gitignore
- .npmignore
- .babelrc

We install the bit utility and initialize a Bit environ:

npm i bit-bin -g
bit init

Next, We track and stage the Delivery-List component. This tells Bit that this is the only file we want to export to its registry.

bit add src/Delivery-List

Netx, we tag the Delivery-List component

bit tag -a 1.0.0

Now create a collection in your Bit account and export the component:

bit export <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>

Go to your collection dashboard you will see the Delivery-List there rendered.

You see we have isolated the only main component from the shared_compos library and shared it singly. There will be no need of all those: .npmignore, package.json, .gitignore, node_modules etc files and folders.

When we want to use the Delivery-List in any project, we just import the component:

Before bit import:

react-prj
- node_modules/
...
- src/
- Display.js
- index.js
- App.js
- App.css
- index.css
- package.json
- .gitignore
bit import <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>/Delivery-List --path src

After bit import:

react-prj
- node_modules/
...
- src/
- components/
- Delivery-List.js
- Display.js
- index.js
- App.js
- App.css
- index.css
- package.json
- .gitignore

Only the component is downloaded no extra files and folders in the node_modules folder.

What have we accomplished here? We simply took a UI library and shared it as a component so we can use it with 0 overhead.

In one of my previous posts, I wrote about on how to publish a React component to NPM. In the post, I demonstrated how to leverage many technologies to write a React component and push it to NPM.

Below is the project folder of the React component.

See so many files and folder (esp node_modules) that is created so we could publish the component to NPM. And on installation for use on a React project, all the folders(node_modules) and files will be downloaded by NPM.

Here, we will see how to single out the TimerComponent and share it to Bit directly from the countdown-timer folder. Bit will resolve it’s dependencies, set and manage its versions and turn this process into a walk in the park.

Let’s move into the countdown-timer folder:

cd countdown-timer

Install Bit and initialize a Bit workspace:

npm i bit-bin -g
bit init

We need to re-structure the src folder to add a sub-directory countdown. We put all the files in the src folder inside the countdown folder with an index.js file and export the component inside the index.js.

...
- src
- countdown
- countdown.css
- coundown.js
- index.js
...
// index.js
export { CountDown } from './countdown.js'

Like this now, Bit will track the component like a dir.

So we have to stage and track the countdown component.

bit add src/**/

The asterisk * tells Bit to stage and track all files in the src folder.

We tag the component so Bit will lock our component with a version.

bit tag -a 1.0.0

We export them

bit export <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>

We have shared the components in the countdown-timer library to Bit. So when we the need arises to use countdown in our React project, we simply import the component:

bit import <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>/countdown --path src
react-prj
- node_modules/
...
- src/
- components
- countdown
- countdown.js
- countdown.css
- index.js
- index.js
- App.js
- App.css
- index.css
- package.json
- .gitignore

We can also share the file that contains our utility functions. Maybe in our project, we have a file util.js that contains functions that perform some basic/complex operations repeatedly.

We have our project like this:

react-app
- node_nodules/
- src/
- utils/
- toString/
- index.js
- looseIdentical/
- index.js
- indexOf/
- index.js
- App.js
- App.css
- index.js
- index.css
- package.json

The utils folder contains sub-folders with functions like:

  • toString
  • looseIdentical
  • indexOf

These functions can be reused in different projects. We might publish them to NPM:

util-funcs/
- src/
- toString/
- index.js
- looseIdentical/
- index.js
- indexOf/
- index.js
- index.js
- .gitignore
- .npmignore
- package.json

To be installed like this:

npm i util-funcs

We can simply share the utility functions from the utils-funcs NPM project without creating another project for an NPM module.

Just, install and initialize the Bit workspace in your folder and track and stage the utility functions.

npm i bit-bin -g
bit init
bit add src/**/

Then, export the staged files to Bit.

bit export <BIT_ACCOUNT_NAME_HERE>.<COLLECTION_NAME_HERE>

We can now import them in our projects. See we can also share functions apart from components. See how good and magical Bit is !!! :)

I love using NPM as it helps us build modular software while reusing packages. Lerna is also great as it helps us publish many NPM modules from the same repo. For smaller components, Bit is GOLDEN.

It turns the dev-experience of making code reusable into an almost instant no-brainer, making each functions/module/component individually reusable. It even lets us develop these components right from any other project too! It even lets you run a TS module in a different JS project 😳 That’s amazing.

We can’t deny the fact that Bit allows us to speed up our development without a total disregard of best development practices and optimization. Bit is easy to use, easy to learn (git-like commands) and most importantly gives a faster development cycle.

Please, feel free to ask if you have any questions or comments in the comment section. Thanks for reading and feel free to try it out!