Think in Component
Bit is a component driven architecture for modern application development based on components. In the world of bit, everything is a component.
Components can be combined into other components to finally form an application app, that is, app is also a kind of component.
This provides a new idea for our development: we build components that can be integrated into different applications, rather than building applications containing components.
Bit helps us build modular, stable, testable and reusable code.
Bit cloud is a cloud hosting service for components. It provides end-to-end solutions for developers and teams to host, organize, retrieve, use, update, and collaborate on processing components.
Bit advantage
- The idea of component architecture helps us build modular, stable, testable and reusable code.
- Separate components from existing code structures without changing the structure or maintaining new projects.
- You can change dependent components and create your own version for independent management without worrying about polluting other environments.
Initialize bit workspace
Install BVM & bit
BVMIt is a bit version management tool, similar to NVM
//Node version above 12.22.0
npm i -g @teambit/bvm
Run BVM – h to check whether the installation is successful. If you remind BVM that the command is unavailable, you need to set the environment variable:
# MacOs Bash
echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc && source ~/.bashrc
# zsh
echo 'export PATH=$HOME/bin:$PATH' >> ~/.zshrc && source ~/.zshrc
# windows
setx path "%path%;%LocalAppData%\.bvm"
Install the latest version of bit:
bvm install
Execute bit – h to check whether the installation is successful. If the reminder bit command is unavailable, you need to set the environment variables according to the above process.
The bit new command initializes the workspace
Applicable to new projects
$ bit new <env> <project>
$ cd <project>
$ bit install
The bit init command initializes the workspace
Applicable to existing projects
- Initialize environment first
$ cd <project>
$ bit init --harmony
- Manually configure the development environment
Take react environment as an example, modify workspace Jsonc file:
"teambit.workspace/variants": {
"*": {
"teambit.react/react": { }
}
}
- Install the necessary peer dependencies
$ bit install react --type peer
$ bit install react-dom --type peer
Initialize Git
You need to add workspace Jsonc and Upload bitmap to GIT.
Create component
Create using built-in components
Take react as an example:
- Create component with built-in template bit create < build in template > < component >
$bit templates # view all built-in templates
$ bit create react-component ui/button # TypeScript
$ bit create react-component-js ui/button # JavaScript
be careful:Among them, < component > can be a path, and the front path is a namespace. The above example is equivalent to bit create react component button — namespace UI.
- Add test case
$ bit install @testing-library/react
- Compile and start service
$ bit compile
$ bit start
Custom components
- Existing component structure and code
- Add components through bit add < relative path > — namespace < namespace >
View component information
You can view all information about the component compilation environment, including files, dependencies, and so on.
$ bit show <component-id>
Example of output information:
┌───────────────┬────────────────────────────────────────────────────────────────────┐
│ id │ my-scope/ui/button │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ scope │ my-scope │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ name │ ui/button │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ env │ teambit.react/react │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ package name │ @my-scope/ui.button │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ main file │ index.ts │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ files │ button.composition.tsx │
│ │ button.docs.mdx │
│ │ button.tsx │
│ │ button.spec.tsx │
│ │ index.ts │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ dev files │ button.docs.mdx (teambit.docs/docs) │
│ │ button.spec.tsx (teambit.defender/tester) │
│ │ button.composition.tsx (teambit.compositions/compositions) │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ extensions │ teambit.react/react │
│ │ teambit.component/dev-files │
│ │ teambit.compositions/compositions │
│ │ teambit.pkg/pkg │
│ │ teambit.docs/docs │
│ │ teambit.envs/envs │
│ │ teambit.dependencies/dependency-resolver │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ dependencies │ [email protected] (package) │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ dev │ @testing-library/[email protected] (package) │
│ dependencies │ @babel/[email protected] (package) │
│ │ @types/[email protected] (package) │
│ │ @types/[email protected] (package) │
│ │ @types/[email protected] (package) │
│ │ @types/[email protected] (package) │
├───────────────┼────────────────────────────────────────────────────────────────────┤
│ peer │ [email protected] (package) │
│ dependencies │ [email protected] (package) │
└───────────────┴────────────────────────────────────────────────────────────────────┘
View component status
$ bit status
View all versions of components
$ bit log <component-id>
View a list of all local components
$ bit list
Start the test server
Run different workspace tasks through worker, such as tests, linkers, and any workspace tasks defined by components.
$ bit compile
$ bit start
Using components
Bit does not support importing another component as a dependencyAllow relative Import paths。 Because this will couple the project specific directory structure, use the package name instead.
To import components as dependencies, you must use module links.
Bit creates a module for each component in the workspace, and these modules are linked in the node_ Modules directory and contains its build output and automatically generated package json。
To regenerate the module link for the component, run the bit link command.
Install components as NPM packages
The install command installs components in the form of NPM package.
As vendor component
The bit workspace gets the component and manages it as if it were a custom component
Install components through the Import command, for example:
$ bit import <component-id>
Update the imported components to the latest version
$ bit import
Convert vendor components to NPM package dependencies
$ bit eject <component-id>
Scope
Scope is the virtual storage of components.
Bit uses scope to save versions of bit components and access them as needed.
Remote Scope
The bit server that hosts the component and its version.
characteristic
Set up scope on the remote server toShared components,Such as bit Dev or self managed bit server.
Storing components on remote scope allows them to be reused in other projects.
- Use the Import command to get components from remote scope.
- Use the export command to push components to remote scope.
be careful:Remote scope caches component dependencies, such as components from other scopes. The advantage of this is to ensure that the current component is executable even if the dependent component is not available.
use
After creating remote scope in bit server, you need to change workspace Jsonc file:
{
"teambit.workspace/workspace": {
"defaultScope": "<bit-username>.<remote-scope-name>"
}
}
workspace. Any changes in the jsonc file require restarting the local development server.
$ bit start
Workspace Scope
Local storage of workspace components.
characteristic
The developer’s workspace holds working copies of components and their history in the local scope. This allows us to browse history, compare versions, and check past revisions of components.
Workspace scope may also contain components from different remote scopes.
Shared components
- Update the version number for the modified component
$ bit tag --all --message "first version"
- Shared components
$ bit export
be careful:When the sharing upload process ends The bitmap file will be updated to reflect this new state.
Install components
Register scope source
$ npm config set '@YourUserName:registry' https://node.bit.dev
Installation dependency
$ npm install @orgName/componentScopeName.componentID
Bit component vs. NPM package
Bit focuses on component-based workflow, and NPM package focuses on compiled output.
- Generating NPM package is only part of the build process of bit component, which is called version artifact by bit.
Configuration
Each component must be configured with an environment so that bit can “know” how to build, test, lint and document components.
teambit. Workspace / variants provides a unified way to set different configuration items for each component without modifying the package under each component file json 。
{
"teambit.workspace/variants": {
"design/theme": {
"defaultScope": "acme.theme",
},
"cart": {
"defaultScope": "acme.cart",
"teambit.react/react": {}
}
}
}
View configuration
- Bit env – prints a simple table that contains all the components in the workspace and their environments
- Bit show < component > – print all the information of the component, including the environment
- Bit start – visual browsing through the browserComponent treeTo view the environment of the component
Remove components
Remove local build
$ bit remove <component-id>
Impact:
-
An untraceable component depends on deleting the component – no impact
- Because bit has not isolated untraceable components, its dependencies will not be detected
- A tracked component depends on deleting the component — it will be warned, and use — force to force deletion
-
The introduced remote component relies on deleting components – no impact
- Because remote components are isolated and cannot be changed
- The remote component is introduced locally and the change creates another version
Remove remote components
$ bit remove <username.your-scope/ui/button> --remote
Describe the impact with an example:
- Button component in remote uiscope
- The card component depends on the button component, which is also in uiscope
- The login component depends on the button component, which is in adminscope
Impact after deleting button component:
-
Because the card component is in the same scope as the button component, there will be a warning when deleting the button component.
- Appendable — force forced deletion
- After deletion, the card component lacks dependencies and needs to be reconstructed to ensure its normal operation
-
The login component has no effect
- Bit will maintain dependencies in scope
-
When other projects depend on the login component, the installation will report an error
- Traceability button component, missing
Compile component
Most modern frameworks require a compilation or translation project to convert source code into executable code that can run in multiple browsers or nodejs.
The bit compiler is an environment service.
The choice of compiler (Babel, typescript, etc.) and its configuration are determined by the various environments it serves.
The compiler will never run directly, but only through the compiler service.
A single workspace may run different compilers for different components, each according to its own environment.
$bit compile < component ID > # compile specific components
$bit compile # compiles all components in the workspace
Component dependency diagram
A key feature of bit is that it can automatically create dependency diagrams according to the source code of components.
JavaScript can declare two types of dependencies using require or import:
- As node_ Modules installed packages
- Files and directories within the project, or referenced in the decorator (for example, in angular)
node_ Modules dependency
Process of bit parsing package (i.e. node_modules):
- You can use bit show < component ID > to check the packages resolved by bit for each package:
$ bit show hello/world
┌───────────────────┬─────────────────────────────────────────────────────────────────────┐
│ ID │ hello/world │
├───────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Language │ javascript │
├───────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Main File │ src/hello-world/index.js │
├───────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Packages │ [email protected]^2.1.0 │
├───────────────────┼─────────────────────────────────────────────────────────────────────┤
│ Files │ src/hello-world/hello-world.js, src/hello-world/index.js │
└───────────────────┴─────────────────────────────────────────────────────────────────────┘
If bit cannot resolve all package dependencies, it will prompt missing package dependencies. We need to verify the package Whether all packages do exist in JSON.
File dependency
Components can rely on other files, such as import/ utils. js。
In order to isolate these components that depend on other files, we also need to track other files that the component depends on. This is because if we want to use this component in another project, the component must have its dependency files.
be careful:Bit uses static code analysis, so it only supports static import and does not support require.
Bit parsing file dependent process
When bit encounters a file that needs to be tracked, it will try to check whether the file has been tracked in another component. In this case, bit will make another component a dependency of the component.
If the file is not tracked, bit will issue an untracked File Dependencies warning when checking the component status.
Isolation problem
To solve the isolation problem, you can:
- Add untracked file dependencies to existing components
- Trace files as new components
Which of the above methods is based on the context of the file. If the file is used by multiple other components, it makes sense to put it in a separate component.
However, if this file is only the internal file of the tracked file, it can be added as the file of the component.
Add files to existing components
Run bit add to point toAdd file componentsID of:
//Examples
$ bit add src/utils/noop.js --id hello/world
Run bit status to check whether it is successful:
$ bit status
new components
> component/hello-world... ok
Files are tracked as new components
You can add new components with bit add
//Examples
$ bit add src/utils/noop.js --namespace utils
The result of execution is a new component.
Privatization deployment V15
Hardware conditions
- Linux / MAC system
- Memory 4G+
Preconditions
- Docker
- Git
#Uninstall old docker
$ yum remove docker docker-common docker-selinux docker-engine
#Installing docker dependencies
$ yum install -y yum-utils device-mapper-persistent-data lvm2
#Set docker source
$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ yum install docker-ce
#Start docker
$ systemctl start docker
#Join startup
$ systemctl enable docker
#Install Git
$ yum install git
Deployment process
$ git clone https://github.com/teambit/bit.git
$ cd bit/scripts/docker-teambit-bit
$ docker build -f ./Dockerfile-bit -t bitcli/bit:latest .
$ docker build -f ./Dockerfile-bit-server -t bitcli/bit-server:latest .
$docker run - DIT bitcli / bit: latest / bin / bash # run
$ docker run -dit -p <port>:3000 bitcli/bit-server:latest
-
Dockerfile-bit:
- Install BVM, and then use BVM to install the docker file of bit.
- This docker is usually useful for running bit commands such as tag and export on CI machines
-
Dockerfile-bit-server:
- A docker file based on dockerfile bit (using from)
- The docker file creates a blank scope and initializes the bit server through bit start on it
-
Dockerfile-symphony:
- For internal use only
Related issues
Mac SSH link: permission denied
$ sudo ssh [email protected]<ip>
SSH link times warning: remote host identification has change
$ sudo ssh-keygen -R <ip>
BVM install cannot install bit
Temporary change of terminal agent
$ export http_proxy=http://127.0.0.1:1087
$ export https_proxy=$http_proxy
be careful:
- VPN required
- Ensure that the browser can access the Internet
- When VPN is enabled, the terminal cannot be proxy even if it is global
Permanent modification agent
#Modify ~ / Bashrc set persistent management script
function proxy_on() {
export http_proxy=http://127.0.0.1:1087
export https_proxy=$http_proxy
Echo - e "terminal agent turned on."
}
function proxy_off(){
unset http_proxy https_proxy
Echo - e "terminal agent is closed."
}
be careful:After modification, use source ~ / Bashrc takes effect immediately.
Through proxy_ On start proxy_ Off closes the agent.
release
Register remote scope
#Client
$ cd <my-project>
$ bit init
$ bit remote add http://<host>:<port>
workspace.jsonc
Configure teambit workspace/workspace
"teambit.workspace/workspace": {
/**
* the name of the component workspace. used for development purposes.
**/
"name": "my-workspace-name",
/**
* set the icon to be shown on the Bit server.
**/
"icon": "https://static.bit.dev/bit-logo.svg",
/**
* default directory to place a component during `bit import` and `bit create`.
* the following placeholders are available:
* name - component name includes namespace, e.g. 'ui/button'.
* scopeId - full scope-id includes the owner, e.g. 'teambit.compilation'.
* scope - scope name only, e.g. 'compilation'.
* owner - owner name in bit.dev, e.g. 'teambit'.
**/
"defaultDirectory": "{scope}/{name}",
/**
* default scope for all components in workspace.
**/
"defaultScope": "remote-scope"
},
Tag
Only by listening to file changes can we identify.
If there is no change in the file, it cannot be identified.
$ bit tag --all --message "first version"
be careful:Independent components form a dependency network through independent “remote scope” and remote component hosting.
This dependency network enables changes to be propagated from one component to all its dependent components. In other words, the change of a component triggers the Ci of the component and the Ci of the component that depends on it in a cascading manner.
give an example:
Component B depends on component A, both of which have an initial version of 0.0.1.
If component A is changed from 0.0.1, A0 will be changed through bit tag — all 0.1 —> 0.0.2,B0. 0.1 —> 0.0.2。
If you continue to change component B, click bit tag — all, B0 Version a – > 0.0.2 unchanged.
Bit deployment
The premise of deployment is to have a new identity. Otherwise, it cannot be deployed.
$ bit export
Extended bit
We extend bit by creating aspect and API accessing bit.
Expand workspace UI
Take the new tab as an example:
Initialize bit environment
$ bit init
It will be created automatically bit/、. bitmap、workspace. Jsonc file (folder).
Modify defaultscope
{
...
"teambit.workspace/workspace": {
/**
* the name of the component workspace. used for development purposes.
**/
"name": "my-workspace-name",
/**
* set the icon to be shown on the Bit server.
**/
"icon": "https://static.bit.dev/bit-logo.svg",
/**
* default directory to place a component during `bit import` and `bit create`.
* the following placeholders are available:
* name - component name includes namespace, e.g. 'ui/button'.
* scopeId - full scope-id includes the owner, e.g. 'teambit.compilation'.
* scope - scope name only, e.g. 'compilation'.
* owner - owner name in bit.dev, e.g. 'teambit'.
**/
"defaultDirectory": "{scope}/{name}",
/**
* default scope for all components in workspace.
**/
"defaultScope": "me"
},
...
}
New aspect
$ bit create aspect aspects/hello-world
Generate directory structure:
.
└──me
└── aspects
└── hello-world
├── hello-world.aspect.ts
├── hello-world.main.runtime.ts
└── index.ts
Among them, hello world main. runtime. The TS code is as follows:
// hello-world.main.runtime.ts
import { MainRuntime } from '@teambit/cli';
import { HelloWorldAspect } from './hello-world.aspect';
export class HelloWorldMain {
static slots = [];
static dependencies = [];
static runtime = MainRuntime;
static async provider() {
return new HelloWorldMain();
}
}
HelloWorldAspect.addRuntime(HelloWorldMain);
be careful:hello-world. main. Runtime is responsible for extending workspace CLI and workspace server.
In order to create a new menu in the component details page, we need to refer to Hello world main. runtime. TS file creates a new Hello world ui. runtime.tsxFile:
// hello-world.ui.runtime.tsx
import React, { useContext } from 'react';
import { UIRuntime } from '@teambit/ui';
import { ComponentUI, ComponentAspect } from '@teambit/component';
import { HelloWorldAspect } from './hello-world.aspect';
export class HelloWorldUI extends React.Component<any> {
static slots = [];
static dependencies = [ComponentAspect];
static runtime = UIRuntime;
static async provider([component]: [ComponentUI]) {
return new HelloWorldUI();
}
}
HelloWorldAspect.addRuntime(HelloWorldUI);
be careful:Componentaspect is introduced here. It is the core aspect of bit and is responsible for building all components and operations of the page. Taking componentaspect as a dependency, we can get it in the provider and use the API it provides.
//Update Hello world.com ui. runtime. tsx
//Register navigation
import React, { useContext } from 'react';
import { UIRuntime } from '@teambit/ui';
import { ComponentUI, ComponentAspect } from '@teambit/component';
import { HelloWorldAspect } from './hello-world.aspect';
export class HelloWorldUI extends React.Component<any> {
static slots = [];
static dependencies = [ComponentAspect];
static runtime = UIRuntime;
static async provider([component]: [ComponentUI]) {
component.registerNavigation({
href: '~hello',
children: 'Hello'
});
return new HelloWorldUI();
}
}
HelloWorldAspect.addRuntime(HelloWorldUI);
Here, we register navigation through registernavigation provided by componentaspect dependency. Manually switching navigation will render hello.
//Update Hello world.com ui. runtime. tsx
//Register registerroute route
import React, { useContext } from 'react';
import { UIRuntime } from '@teambit/ui';
import { ComponentUI, ComponentAspect } from '@teambit/component';
import { HelloWorldAspect } from './hello-world.aspect';
export class HelloWorldUI extends React.Component<any> {
static slots = [];
static dependencies = [ComponentAspect];
static runtime = UIRuntime;
static async provider([component]: [ComponentUI]) {
component.registerRoute({
children: () => <div>hello world</div>,
path: '~hello'
});
component.registerNavigation({
href: '~hello',
children: 'Hello'
});
return new HelloWorldUI();
}
}
HelloWorldAspect.addRuntime(HelloWorldUI);
Here, we register the route through the registerroute provided by componentaspect dependency. The route will undertake the navigation of the above registration and simply render Hello world.
Register custom aspect
Before executing an aspect, it needs to be configured with a parsing environment, which will eventually translate the aspect into code recognized by the browser and nodejs.
{
...
"teambit.workspace/variants": {
"{me/aspects/*}": {
"teambit.harmony/aspect":{}
}
},
"me/aspects/hello-world": {}
...
}
Installation dependency
$ bit install
Without installing dependencies, bit start works normally, but you can’t see the added UI.
Effect display
Run bit start to check the effect ~
be careful:To update the presentation, delete it bit/、node_ Modules, public /, and execute bit install and bit start again.
View aspect information
You can view the information through bit show me / aspects / Hello world
Create extensions from built-in templates
- View built-in templates through bit templates
- Through ` bit create < template > < custom name > [– scope scope name]
- Install template related dependencies through bit install
- View custom extension status through bit status
- If there is an error in missing dependency, add the missing dependency to:
"teambit.dependencies/dependency-resolver": {
/**
* choose the package manager for Bit to use. you can choose between 'yarn', 'pnpm'
*/
"packageManager": "teambit.dependencies/pnpm",
"policy": {
"dependencies": {},
"peerDependencies": {
"react": "~17.0.2",
"@testing-library/react": "~12.1.2"
}
}
},
Bit install supplements installation dependencies.
- Pass the bit start — dev test.