Build Bit components in your existing project

ed
eden-e10 months ago

This blog will guide you through the following steps:

  1. Create independent Node and React components in an existing project
  2. Use the new components in this project

Our existing project: React + Express 'hello-world' application

Our legacy app for this tutorial is a React + Express 'Hello-World' application. It displays a button that fetches the 'hello world' string from the server.

Clone the pre-bit project, to follow along:

$git clone https://github.com/bitdev-community/fullstack-legacy-with-bit.git
Copiedcopy

To run this project, run npm install && npm start in the root directory.

The project structure looks similar to this:

. ├── api │ └── src │ ├── routes │ │ └── hello │ ├── app.ts │ └── index.ts ├── web │ └── src │ ├── hooks │ │ └── use-hello-world │ ├── pages │ │ └── landing-page │ ├── ui │ │ ├── button │ │ └── heading │ ├── app.tsx │ └── index.tsx ├── package-lock.json └── package.json

Initialize a Bit workspace

Initialize a Bit workspace in the root directory of the project:

$bit
Copiedcopy
See command synopsis

learnbit.bit-pioneers is the default scope for components in this workspace. Replace this with your own scope name.

The output should look similar to this:

successfully initialized a bit workspace.

Bit has generated a workspace with the minimum necessary files, to prevent any possible conflicts with your current project. These files include the workspace.jsonc, for your workspace configuration, the .bitmap file which maps components to their directories in your workspace, and the .git/.bit hidden directory.

Run the Workspace UI (optional)

The Workspace UI is a visual representation of your workspace. It is not required for this tutorial, but it's a great way to get a better understanding of your workspace, and to visualize the components you maintain in it. (the components' instances for rendering are loaded from their *.compositions.* files, placed in their directory)

To run the Workspace UI, run the following command:

$bit
Copiedcopy
See command synopsis

Head over to your browser and navigate to http://localhost:3000. Note that the workspace is currently empty as there are not Bit components in it yet.

In futures steps, we'll add components to the workspace. These components will then appear in the Workspace UI. If that does not happen, try restarting the Workspace UI.

Create Bit components

Create new components using component templates to get you started quickly with pre-made source files and configurations.

In this tutorial, we will create two components: a React 'loader' (spinner) component and a Node Express 'goodbye' route component. The components will be created using component templates. These templates generate a few source files and configurations. One important configuration is the env property which determines the component development environment to use. In this case, one component will be developed using the React env, and the other using the Node env.

We highly recommend creating your own React and Node envs. This will allow you to customize the development tools and configurations to your needs. See Set up your React env and Set up your Node env for more information.

Module types

Your env determines which module type your components are be compiled to.

Choose an env, or customize your own, based on the module type you want to use. In this tutorial, we'll use a React env that compiles components to ES modules, since the rest of the frontend app compiles to ES modules.

Conversely, we'll be using a Node env that compiles components to CommonJS modules, since the rest of the backend app compiles to CommonJS modules.

React 'loader' component

To create a new React component, we'll use a template provided by the basic React env, and run the following command:

$bit
Copiedcopy
See command synopsis

The output should look similar to this:

1 component(s) were created

learnbit.bit-pioneers/routes/goodbye
location: components/ui/loader env: teambit.react/react-env (set by template) package: @learnbit/bit-pioneers.ui.loader

See the 'loader' component implementation in this workspace and scope.

Node 'goodbye' route component

To create a new Node component, we'll use a template provided by the basic Node env, and run the following command:

$bit
Copiedcopy
See command synopsis

The output should look similar to this:

1 component(s) were created

learnbit.bit-pioneers/routes/goodbye
location: components/routes/goodbye env: teambit.harmony/node (set by template) package: @learnbit/bit-pioneers.routes.goodbye

See the 'loader' component implementation in this workspace and scope.

Using the components in the project

Components are consumed using the Node package generated for each of them. In development, the package is generated in the node_modules directory of the project, and can be imported like any other Node package. During the components' build a similar package is generated as part of the component's build artifacts, and is used to consume the component in other projects. More on that in the next sections.

The server for the workspace UI also compiles modified components. If you're not using it, make sure to run the compilation in watch mode, to make sure the component packages (containing the compiled code) are always up to date.

$bit
Copiedcopy
See command synopsis

The output should look similar to this:

Watching for component changes (14:32:53)...

Import the components to the relevant files in the project:

React
Backend (NodeJS)
/* @filename: web/src/pages/landing-page/landing-page.tsx */

// ...

/* this is a bit component. it is consumed using its package */
import { Loader } from '@learnbit/bit-pioneers.ui.loader';

// ...

export const LandingPage = ({ className, ...rest }: LandingPageProps) => {
  const [helloWorldState, fetchHelloWorld] = useHelloWorld();

  if (helloWorldState.loading) {
    return <Loader />;
  }

  return (
    <div className={cx('container', className)} {...rest}>
      {helloWorldState.data ? (
        <Heading>{helloWorldState.data}</Heading>
      ) : (
        <Button onClick={fetchHelloWorld}>Load Data</Button>
      )}
    </div>
  );
};
CopiedCopy

Component dependencies

Dependencies used by your components can be installed using your current package manager (npm, yarn, pnpm, etc.). These dependencies will be added to the project's package.json file.

The type of a dependency is determined by the components. For example, if a component uses @testing-library/react, in one of its dev files, this dependency will be listed as a devDependency, regardless of the dependency type in the project's package.json file.

Ensure your components are always consumable by your project

In previous sections, we've seen how components are consumed in the project using their Node package (and never using relative paths to their source files).

To make sure your components are linked from the node_modules directory, and compiled, add the following to the "postinstall" script to your package.json file:

{
    "postinstall": "bit compile && bit link"
}
CopiedCopy

Further reading