How to Collaborate on Components across Projects with Bit
Tags: react, javascript, githunt, git
Published: 2021-07-02 21:11:22

Most of us build our web projects with components. It makes our code more reusable, more maintainable, more testable, and easier to understand and debug.

We often share a few of these components, to be able to use them across projects. A "design system" for the UI, and some sort of a "toolbox" with util functions, for our logic.

> Why, then, do we stop there? Why not share and collaborate on everything? 

Truth is, it's not that easy to share and collaborate on components. You can group components together in the same repository and publish them as a single package, but then, you're not really "collaborating on components", you're collaborating on a project.

What you really need is a way to develop, share and modify _individual components_ from any project. Why? Because being able to pick and choose the components (and component versions) for your project, and being able to propose changes, increases the likelihood that these components will actually be used (and reused). 

That naturally translates to faster development and higher standard of code.  

## Introducing Bit - an end-to-end solution for component-driven development.

[Bit](https://github.com/teambit/bit) is an extensible development platform that offers everything you need to collaborate on components (that is, instead of _only_ collaborating on projects)

Let's start with Bit's essential features:

* __Component source-control__ - essentially, git for individual components.

* __Isolated component development__ - that includes isolated rendering, tests and builds.

* __Component dependency management__ — auto-generated component dependency graphs, and smart dependency management. That includes _two types of dependencies_: node packages and other components (more on that, later).


## The workflow
We will create a Bit workspace, version it using git, and (on top of that) version each of our components (managed by the workspace) _independently_, using Bit. 

Two layers of version-control, one for our entire project and another for our components. As you'll soon see, the two work in harmony to produce better, more effective, collaboration on code.  

[Bit](https://github.com/teambit/bit) will not only version each component independently but will also enable us to develop, test and build, each of them independently. 

* Our project repository (the Bit workspace) will be pushed to Github.

* Our components (source-controlled by Bit and managed by the Bit workspace) will be pushed to a remote Bit scope 

* To collaborate on components before they are tagged with a new release version, we will _suggest_ a new release version  by updating our workspace. Once that workspace is pushed to Github, the CI (Github Actions) will act on these suggestions, tag the suggested components with a new release version and push them to a remote Bit scope (where they can be cloned into other Bit workspaces).

### 1. Initialize Bit and git
A Bit workspace is where multiple components are developed and composed together, while maintaining each as an independent project.

```shell
$ mkdir my-workspace   # create a directory for our workspace
$ cd my-workspace      
$ git init             # initialize git
$ bit init --harmony   # initialize Bit
```

The following files were created:

```
├── my-workspace
    └── .git
       ├── bit
       ├── ...
    ├── .bitmap
    └── workspace.jsonc
```

`workspace.jsonc` - The workspace configuration file that sets rules and policies for the workspace and all its components. 

Notice there is only one configuration file for all our future components. That's possible thanks to Bit's CSS-like configuration system, where group of components are selected and configured together, and where specific selections override the more general ones. 

`.bitmap` - This is where component files are mapped to component IDs, so that Bit would track them and manage them as a discrete unit (essentially, this is where the "isolated development" starts).


`.git/bit` - Your local scope. Where your workspace component repositories are stored. 


### 2. Create component files, source-control and manage them as independent components

Let's create two React components, a 'button' and an 'app-bar'. Each component will have its own directory. 

```
├── my-workspace
    ├── .git
    ├── components
       ├── button
       └── app-bar
    ├── .bitmap
    └── workspace.jsonc
```

Each will have the following files:

`*.ts` - the component implementation files
`*.compositions.tsx` - the component isolated previews
`*.spec.ts` - the component tests
`*.docs.mdx` - the component docs
`index.ts` - the component entry file

To track them we'll run:
```shell
$ bit add components/button
$ bit add components/app-bar
```

Our components are now each managed and source-controlled independently.

Our tracked components are now also visible in Bit's workspace UI. To see them, run Bit's server, and open `localhost:3000`

```shell
$ bit start
```

![An example workspace UI](https://miro.medium.com/max/2000/1*Dc5rFCUOOLuEu7oTs8Up9g.png)


### 3. Run each component's CI and tag it with a new release version

Our components are ready to be built and tagged with a new release version.

We'll version button as `1.0.0`, and `app-bar` as `0.0.1`.

```
$ bit tag button 1.0.0 --message "public release"
$ bit tag app-bar 0.0.0 --message "initial version"
```

The above `tag` command will not only version our components but will also build them each in their own isolated environments. That is, it will copy their source files and configurations (set in the `workspace.jsonc`) to a directory that is isolated from the rest of the workspace. Once that's done, it will test and build them. 

> The build workflow, the test runner, the compiler, the linter, and other development tools - are all determined by a pre-configured shareable component development environment. Learn more about it [here](https://harmony-docs.bit.dev/).


The artifacts produced by the build process will all be versioned as well, along with each component's source-files and configurations. 

![A component Bit repository](https://miro.medium.com/max/2000/1*nDNK-OF3smGAykpiN2b76A.png)

One of the versioned artifacts is the component's package (with an auto-generated `package.json` file). The package is used by other components when:

* Using a component authored in the same Bit workspace
* Using a component cloned into a Bit workspace
* Using a component installed (as a package) using Bit or any other npm client

...

## Collaborating on components

### 4. Export (push) and import (clone) components
Just like git repositories are pushed to remote hosting (like Github) so do [component repositories](https://blog.bitsrc.io/independent-components-the-webs-new-building-blocks-59c893ef0f65) are pushed to remote Bit hosting, remote "scopes".

__To 'export' (push)__ components to remote scopes, run:

```
$ bit export
```
The remote scope to push the components to, is set in the `workspace.jsonc` configuration file. 

A remote scope can be created on [bit.dev](https://bit.dev) for free, or [by hosting on your own server](https://harmony-docs.bit.dev/reference/bit-oss-server/). 


__To 'import' (clone)__ a component into a Bit workspace, run:

```shell
$ bit import <component-id>
```

Shared components can be found on [bit.dev](https://bit.dev) (or on your self-hosted Bit scope).

### 5. Suggest a new component release version with Bit and git

Instead of locally tagging a component with a new release version (and exporting it from your local machine), we can run: 

```shell
$ bit tag --soft <component-id> <new-version>
```
This will update the `.bitmap` file with the suggested version (without actually tagging the component with a new release version). 

Once we push the workspace to Github (along with the .bitmap file) others can review the suggested changes, and your CI can “hard tag” the suggested component versions. and export them. Learn more about this process here.

```shell
$ git commit -am "change the button font. suggest new release version"
```

### 6. Push the Bit workspace to Github and Run a CI to tag the modified component with a new release version

* Go to Github and create a new secret variable in your Github repository. 

* Name it `BIT_TOKEN` and set the value of it to the `user.token` value.

* Create a new `tag-and-export.yml` file in your remote repository `./.github/workflows` directory.

* Create your script:

```yaml
# This workflow hard-tags and exports soft-tagged components
name: Tag and Export Components

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  tag-and-export:
    runs-on: ubuntu-latest
    if: "!contains(github.event.head_commit.message, '--skip-ci')"
    env:
      BIT_TOKEN: ${{ secrets.BIT_TOKEN }}

    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js 12
      uses: actions/setup-node@v1
      with:
        node-version: 12.x
    - name: Install Bit Version Manager 
      run: npm i -g @teambit/bvm
    - name: Install latest Bit version 
      run: bvm install
    - name: add bvm bin folder to path
      run: echo "$HOME/bin" >> $GITHUB_PATH
    - name: Set up bit config
      run: |
          bit config set analytics_reporting false
          bit config set anonymous_reporting false
          bit config set user.token $BIT_TOKEN
    - name: Install packages using bit
      run: bit install
    - name: Hard-tag pending components
      run: bit tag --persist
    - name: Export components
      run: bit export
    - name: Commit changes made to .bitmap
      run: |
        git config --global user.name '${{ github.actor }}'
        git config --global user.email '${{ github.actor }}@users.noreply.github.com'
        git add .bitmap
        git commit -m "update .bitmap with new component versions (automated). --skip-ci"
        git push
```
The above script installs Bit, hard tags the new release suggestions (found in the `.bitmap` file), exports the newly tagged versions and commits the changes made to the `.bitmap` file (the release suggestions have been replaced with new releases).

See demo project on Github:

{% github https://github.com/teambit/harmony-with-github-actions %}

Learn more about Bit:

{% github https://github.com/teambit/bit %}