什么是 Bit
Bit 是一个开源工具,利用 Bit 我们可以搭建由组件驱动的应用。 Bit 并不规定如何去创建整个应用,其只是帮助你来定义组件,并使用这些组件来构成应用,并且 Bit 会为你的每个组件提供其最适合的开发工具
我们可以用 Bit 来做很多东西,比如使用 Bit 结合由组件驱动的框架(React、Vue、Angular)来做 PC 的应用或者是微服务框架,CLI 工具集,桌面端或者是移动端项目,基本上只要是能够用 JS 做到的 Bit 都能够做而且远不止于此。
痛点
幽灵依赖(Phantom dependencies)
管理 monorepo 的痛点之一便是依赖管理。在一个 monorepo 中,你可能每个 package 都有自己的 package.json 以及其自己的生产和开发依赖。 当你使用 npm 来管理你的 workspace 时,其会将所有 package 的所有依赖放在 monorepo 的根目录下,如果你有一个组件用了依赖 A,另外 一个组件用了依赖 B,那么会有如下的依赖结构
css
workspace
├── node_modules
│ ├── A
│ └── B
├── button (dependencies: {A: '1.0.0'})
└── card (dependencies: {B: '1.0.0'})
尽管 button 组件仅依赖 A,但是其是可以引用 B 依赖的,如果在 button 组件中引用了依赖 B 且其被当做依赖时,代码就会运行失败。
不过还好,npm 或者是 yarn 2.x+ 在使用默认配置去进行依赖安装时,并不会出现幽灵依赖的问题
less
workspace
├── node_modules
│ └── .pnpm
│ ├── A@1.0.0/node_modules/A
│ └── B@1.0.0/node_modules/B
├── button
│ └── node_modules
│ └── A --> ../../node_modules/.pnpm/A@1.0.0/node_modules/A
└── card
└── node_modules
└── B --> ../../node_modules/.pnpm/B@1.0.0/node_modules/B
在这种情况下,button 组件与依赖 B 并无关系,即便是尝试在 button 组件中去引用 B,其也会在开发环境中报错
开发依赖(devDependencies)
开发依赖的问题不仅仅出现在 monorepo 中,可能一个 package 顺利的通过了运行时的使用和功能测试,在本地各种好使,但是当其被当作一个依赖被引用时, 由于其缺少了开发依赖,故而会导致问题的出现,
依赖版本管理
同一个依赖可能被多个 package 引用,该依赖版本可能重复出现在不同 package 的 package.json 中,如果我们想管理好这些依赖的版本的话通常很难而且经常需要借助工具,比如syncpack
Bit 带来的良好的体验
Bit 能够在解决以上痛点的同时,给您带来良好的管理体验:您仅需要记住运行bit status
并安装您所缺少的依赖即可,Bit 会将这些依赖作为 workspace 的依赖,而非单个 package 的依赖
Bit 的理念
Bit 是为渐进式而设计的,在引入新的技术、框架或工具时,以渐进的方式进行采用和应用。这意味着不会突然地完全转变或替换现有的系统,而是通过逐步迁移、逐步应用的方式,让新的技术逐渐融入现有的系统中。这种渐进的采用方法有助于降低风险,并允许团队逐步熟悉和适应新的技术,同时保持现有系统的稳定性。Bit 其与您如何构建项目无关且 Bit 符合当前的社区标准同时其所需空间小
Bit 的基本使用
安装 Bit
bash
npx @teambit/bvm install
这里我们实际上使用了 BVM 来协助安装 Bit,BVM 是 Bit 的版本管理器,这使得我们能够更加方便的下载和管理 Bit
创建工作空间
工作空间是一组文件和目录,其为组件的组合和版本控制提供了上下文
您利用 workspace starter 来创建一个新的 workspace
arduino
// bit new WorkspaceTemplate WorkspaceName AspectId DefaultScope
// 运行以下命令
bit new react tasks-workspace --aspect teambit.react/react-env --default-scope my-org.tasks-scope
- WorkspaceTemplate:工作空间模板,在 workspace 外运行
bit templates
来获取当前可用的 workspace 模板 - WorkspaceName:工作空间名字,如果不存在则会被创建
- AspectId:注册 workspace 的切面的 id,对于非核心切面是必要的,有助于解决命名冲突的问题
- DefaultScope:组件的默认作用域
您会看见如下输出,
arduino
Let's get started!
cd tasks-workspace
bit start
依次执行命令后,您会看见如下输出
csharp
You can now view 'tasks-workspace' components in the browser.
Bit server is running on http://localhost:3000
您访问这个网址http://localhost:3000
,在该页面中您可以概览当前 worspace 的组件状况并进行一定的管理
组件状态
在组件开发的任意时刻您可以利用bit status
来查看当前 workspace 中的组件状态以及检测到的问题,同时您可以运行bit list
来获取组件列表
到目前为止您已经成功利用 Bit 创建了一个属于您自己的 workspace!
arduino
Inside the directory 'my-vue-hello-world' you can run various commands including:
bit start
Starts the local dev server
bit install
Installs any missing dependencies
bit status
Shows the status of the components
bit compile
Compiles the components
bit test
Runs the tests on all your components
bit templates
Shows all available component templates
bit help
Shows all available commands
Let's get started!
cd my-vue-hello-world
bit run hello-world-app
bit start
技术集成
Bit 天生支持多种多样的开发工具,比如 TypeScript, Babel, Jest, Webpack, ESLint,并且对于 React, Vue, NodeJS, Angular 这些组件驱动的框架已经有了现成的开发环境了。而且 Bit 的理念是------技术栈的无知论者,其计划在将来 支持其他高级语言,所以无论从现状还是理念来讲,Bit 的技术集成做的还是蛮不错的
Important Concepts
组件
Bit 位于产品和工程的交叉点上。它可以帮助你处理复杂的产品需求,并将它们分解为独立的、可重用的部分,称为"组件"。 它允许你创建组件并将它们组合在一起。组件由名称和 API 组成。组件可以是不同类型的,如 Web App、页面、UI 组件、后端服务。
组件可以像一个现代 Web 应用那么大,也可像一个 UI 组件那么小,每一个 Bit 的组件,无论其是大还是小,其都是其他组件的一部分,并且每个组件都是独立维护的
工作空间 Workspace
工作空间是一种上下文环境,其为组件的定义、组合与组件的版本管理提供了条件。
一个工作空间可以被用作一个临时的组件维护的环境,或者是可以联合常用的 VCS(版本管理系统)比如 git,来作为一个长期的项目合作的容器。但是无论哪种方式来使用工作空间, 每个组件只要被版本管理后,其都是从工作空间中独立且解耦出来的。
作用域 Scope
工作空间通过作用域的形式来组织管理组件,作用域是组件的所有者,组件通过作用域与外部进行交流协作,因此作用域为组件提供了一种协作模式。
使用.
作为分隔符,以组织.团队
的模式来命名你的作用域,比如teambit.docs
意为该作用域由 teambit 旗下的 docs 团队所拥有
组件环境 Env
组件环境,顾名思义,组件开发时的环境,其为组件的开发提供了一系列的工具和配置; 工具
- Compiler:编译器,用于对组件进行编译操作
- Tester:测试器,用于对组件进行测试操作
- Linter:代码检查器,用于对组件代码规范性做出检测
- Formatter:格式器,用于对组件代码格式做出规范
- Component generators:组件构造器,用于快速构建一个组件的基本架构
- Workspace starters:工作空间构建器,用于快速构建一个工作空间的基本架构
组件环境也是一种组件,其也可以像组件一样在团队之间进行分享,这样能够有效的统一标准
注意:一个工作空间内可以有多个 Env,且每个组件仅能够有一个 Env,该 Env 可以进行配置
包 Package
包是组件发布过程的一个中间态,包能够使得组件被包管理器下载并应用
包是一种机制,使得组件无论是否在 Bit 环境下都能够被使用,为了维持这种机制的稳定性,每个包都有一个由 Bit 自动生成的package.json
文件来维护组件的相关信息
应用 App
应用也是组件的一种具体形式,应用由组件构成,应用包含了其所有用来构建和发布用的信息
切面 Aspect
Bit 是由组件驱动的架构创建的,而这个架构中有个系统叫做 Harmony,Harmony 系统能够整合组件来为 Bit 创建特性,比如为 Bit 的某个 API 创建实现。
Harmony 最基本的单元就是切面,切面是一种跨技术栈的特性,其适用于前后端等运行时环境,切面之间互相合作构成 Bit 的特性,Bit 使用切面来扩展自身。
注意:切面也是组件的具象化
结合 Vue 使用 Bit
创建 Env
通过以下两条命令创建以 vue 为模板的 workspace,并在其中使用 Bit 提供的 vue-env 模板来创建一个组件
bit
// 如果你没有命名空间可以使用该命令来创建一个新的命名空间的同时使用Bit 提供的 vue-env 模板来创建一个组件,并将其放在my-scope这个作用域下
bit new vue my-workspace --env teambit.vue/vue --default-scope my-org.my-scope
// 如果已经有了命名空间,则直接使用以下命令向命名空间中添加vue-env为模板的组件
bit create vue-env envs/my-vue-env --aspect teambit.vue/vue
我们创建 Env 的目的是为了使用其提供的一系列组件构建工具来帮助我们创建组件
使用 Env
有了 Env 之后,我们就可以利用组件的 Env 提供的组件构建工具Component generators
来快速创建一个组件,Component generators
为组件的构建提供了多个模板,我们将在这些模板上创建自己的组件
使用 Env 的前提
我们需要确保自定义的 Env 被正确的配置到了workspace.jsonc
,这样可以确保我们在构建相关组件时,能够使用正确的 Env
json
/* @filename: workspace.jsonc */
{
"teambit.generator/generator": {
"envs": ["my-org.my-scope/envs/my-vue-env"]
}
}
获取可用模板
运行以下命令去获取当前 workspace 中可以使用的模板
arduino
bit templates
当 Env 被正确的配置到workspace.jsonc
文件中时,我们可以看见如下输出
sql
The following template(s) are available with the command bit create:
Example - bit create <template-name> <component-name>
my-vue-env (xuanyu.vue-scope/envs/my-vue-env)
vue (A vue component template. Can be used for Vue components.)
vue-composable (A vue composable template. Can be used for Vue composables.)
vue-app (A vue application template. Can be used for Vue applications.)
vue-env (A vue env template. Can be used for creating your own Vue env.)
使用模板构建组件
按照bit templates
的提示,我们使用被收集到workspace.jsonc
的 Env 来构建一个组件
arduino
bit create vue pages/welcome
会看到以下输出结果
kotlin
1 component(s) were created
xuanyu.vue-scope/pages/welcome
location: vue-scope/pages/welcome // 组件在工作空间的地址,作用域名/****/组件名
env: xuanyu.vue-scope/envs/my-vue-env (set by template) // 构建组件所采用的Env
package: @xuanyu/vue-scope.pages.welcome // 组件的package名
由此我们便成功的使用 Env 提供的Component generators
快速的创建了一个 Bit 标准的组件
Vue 组件
组件命名
组件命名需要遵循如下规则:
- 组件名长度要大于零
- 组件名中出现的字母全都要小写
- 组件名能够包含连字符
- 组件名的起始和末尾不能出现空格
- 组件名不能包含这些特殊字符:
~)('!*
- 组件名不能是
node.js/io.js
核心模块的名字,也不能是保留包名/黑名单包名 - 组件名长度不能超过 214
组件 ID
组件 ID 是一个人类能够读懂的的唯一标识符,通常我们能够通过组件的 ID 读取到一个组件的目的、上下文和所有者
namespace 是组件的类别所在,当我们在 workspace UI 页面时,便能看到组件所在的类别
当一个新的组件被创建时,其 ID 会被记录在工作空间的.bitmap
文件中,这样其组件在被导入与导出时使用的就是同一个 ID
我们能够快速的通过bit list
来查看命名空间内的所有组件
组件内容
以上述组件为例,使用 Env 的Component generators
生成的组件包含以下文件,接下来我们逐步讲解这些文件的作用
- index.ts
- welcome-basic.fixture.vue
- welcome.composition.ts
- welcome.docs.md
- welcome.spec.ts
- welcome.vue
实现 Implementation
组件的主要内容定义在welcome.vue
文件中,我们可以自主修改来定义组件的内容
组合 Compositions
组合(Compositions):用于校验组件在相关上下文环境或者是变种情况下是否表现正常
比如我们可以看到组件文件中含有welcome-basic.fixture.vue
,该文件是由Component generators
自动生成 是组件 Compositions 的基本示例
vue
<!-- @filename: welcome-basic.fixture.vue -->
<script setup>
import Welcome from "./welcome.vue";
</script>
<template>
<Welcome title="Hello World" />
</template>
这个示例中做了两步:1.引入需要进行组合的组件 2.使用该组件
然后welcome-basic.fixture.vue
又被welcome.composition.ts
所导入并导出
welcome.composition.ts
文件的作用就是导入组件的所有 Compositions 情况并交由 Bit 的 workspace UI 来进行展示(运行bit start
来启动 Bit 的 workspace UI )
然后我们在组件的 Compositions Tab 下即可查看到该组件的 Compositions 情况,从而校验组件在相关上下文以及变种的情况下是否表现正常
我们可以自己添加额外的 Compositions 情况,注意,自己添加的 Compositions 情况需要放在命名符合*.fixtures.vue
规则的文件中,以下是一个例子
vue
<!-- @filename: welcome-testComposition.fixtures.vue -->
<script setup>
import Welcome from "./welcome.vue";
</script>
<template>
<Welcome title="Composition" />
</template>
仍旧是两步:1.引入需要进行组合的组件 2.使用该组件
然后在welcome.composition.ts
中导入该 Composition
ts
import BasicWelcome from "./welcome-basic.fixture.vue";
import CompositionWelcome from "./welcome-testComposition.fixtures.vue";
export { BasicWelcome, CompositionWelcome };
然后我们去到 workspace UI,找到该组件的 Compositions Tab 去检查是否符合预期即可
测试 Tests
Bit 在组件的.spec.ts
文件中对组件进行测试,我们可以在该文件使用Vue Testing Library来作为组件的测试工具
以下是一个例子,具体的该如何测试请查看Testing
ts
import { render } from "@testing-library/vue";
import { BasicWelcome } from "./welcome.composition";
it("should render with the correct text", () => {
const { getByText } = render(BasicWelcome);
const rendered = getByText(/Hello World/);
expect(rendered).toBeTruthy();
});
说明文档 Documentation
我们可以手动编写welcome.docs.md
来为 Welcome 组件来编写说明文档,文档使用 Markdown 语法,可以查看Markdown Guide来获取 Markdown 语法信息
以下是一个例子
yaml
---
description: A my-counter component.
---
A component that does something special and renders text in a div.
### Component usage
```vue
<template>
<MyCounter title="Hello World!" />
</template>
```
使用依赖
对于 Bit 组件而言有两种依赖 1.第三方包 2.自定义组件
第三方包
如果是第三方包的话,需要使用bit install
来进行安装,我们以VueUse为例
arduino
bit install @vueuse/core
然后在其他组件中导入该包
vue
import { useCounter } from "@vueuse/core";
自定义组件
如果是想引入自定义组件的话,我们在导入时,其包名为自定义组件的包名
以 Welcome 组件为例,运行bit show pages/welcome
来查看该自定义组件的包名 或者是使用 workspace UI 找到对应组件,也能获取其包名
然后在其他组件中导入该自定义组件
vue
import Welcome from "@xuanyu/vue-scope.pages.welcome"
Vue App
App 也是组件的一种具象化,其可以使用自定义组件(Components)或者是第三方包(Dependencies)来作为依赖,但是 App 不应该存在同层级的组件,应用应该是组件的消费者而非生产者。
创建 App
使用以下命令来创建一个 Vue app
arduino
bit create vue-app apps/my-app
我们会看见如下输出
kotlin
1 component(s) were created
xuanyu.vue-scope/apps/my-app
location: vue-scope/apps/my-app // app所在地址
env: xuanyu.vue-scope/envs/my-vue-env (set by template) // 构建app的Env
package: @xuanyu/vue-scope.apps.my-app // app的包名,供外部引用
App 文件中包含一个my-app.vue-app.cjs
文件,此文件为该 Vue app 的配置文件(该文件后缀为 cjs 是因为该文件需要在 Node 环境下运行)
一个应用可以有多个配置文件,配置文件的后缀代表着该应用的类型,Bit 会根据应用类型的不同在应用构建和发布时采用不同的策略,例如一个应用可以使用UMD
或者ES6
或者别的模块策略来进行打包
以.vue-app.cjs
为例,当应用的配置文件的后缀为.vue-app.cjs
时,Bit 会将其视作一个 vue 应用,并在该应用在构建和发布时采用 vue 相关的构建和发布策略。 另外我们在该文件内可以对 App 做一些配置,例如在下例中,我们配置了该应用的入口和名字
cjs
/**
* Modify this file to change webpack config or add a deployment
* for your vue application.
*
* @see https://bit.dev/docs/apps/vue-app-build#modify-webpack-configuration
* @see https://bit.dev/docs/apps/vue-app-deployment#use-a-deployer
*/
/** @type {import("@teambit/vue.apps.vue-app-types").VueAppOptions} */
module.exports.default = {
name: "my-app-app",
entry: require.resolve("./my-app.root"),
};
App 与 Aspect
当组件含有 App 配置文件时其被视为一个应用,在 Bit 的概念中,应用同时也是一个切面,因此,在应用构建完毕之后,我们应该使用bit use
来在workspace.jsonc
中登记该应用
perl
bit use apps/my-app
将组件转化为应用
当组件含有 App 配置文件时其被视为一个应用,因此我们需要在组件的根目录中添加一个应用配置文件,注意,应用配置文件的后缀决定了该应用的类型
以下为一个应用配置文件的例子
cjs
// my-app.vue-app.cjs
module.exports = {
name: "my-app",
/* provide your bundler with an app entry file */
entry: [require.resolve("./my-app.app-root")],
};
为了使工作空间能够顺利的将该应用用作一个切面,我们需要使用bit use
来在工作空间中登记该应用
perl
bit use apps/my-app
常用命令
bit install
bit install [packages...]
为工作空间安装依赖
bit uninstall
bit uninstall [packages...]
为工作空间卸载依赖
bit list
查看工作空间中所有的组件 ID
bit new
从模板创建一个新的命名空间
bit new <模板名> <命名空间名>
bit create
bit create <template-name> <component-name>
:使用模板创建一个新的组件
bit create <template-name> <component-name> -s <string> -n <string>
:使用模板创建一个新的组件,并手动指定作用域、命名空间
bit show
bit show <component-id>
:展示组件的相关信息
bit app
bit app list
查看所有使用 bit use
进行注册的组件列表
bit app list -j
:使用 JSON 格式返回组件列表
bit app run
bit app run <app-name>
,本地运行 bit app
bit app run <app-name> -d
:以开发模式启动 app
bit app run <app-name> -p [port-number]
:app 的端口
bit add
bit add [path...]
将指定目录下的文件夹收录为工作空间内的一个组件
bit add [path...] -i <name>
将指定目录下的文件夹收录为工作空间内的一个组件,并手动设置组件 id
bit add [path...] -m <file>
将指定目录下的文件夹收录为工作空间内的一个组件,并手动设置组件入口文件
bit add [path...] -n <namespace>
将指定目录下的文件夹收录为工作空间内的一个组件,并手动设置组件入口文件
bit add [path...] -s <string>
将指定目录下的文件夹收录为工作空间内的一个组件,并手动设置组件作用域
bit remove
bit remove <component-pattern>
将符合组件匹配模式的组件从工作空间中移除,component-pattern:组件匹配模式,可以是组件名,组件 id
bit remove <component-pattern> --keep-files
将符合组件匹配模式的组件从工作空间中移除,但是不删除组件文件
创作不易,点个赞吧。