bit 工作流

2,223 阅读4分钟

bit 官网: docs.bit.dev/docs/quick-…

什么是 bit

Bit is the platform for collaboration on atomic components

组件共享方式对比

当在 A 项目中发现一个组件 B 项目中可以很好的复用,这时候会有以下几种方式来实现:

  1. 复制粘贴
  2. 维护一个单独的组件库
  • 将代码提取到其自己的存储库中
  • 配置构建工具
  • 构建发布链 需要单独的人力成本维护,而且不支持在其他项目的定制化开发,如发现有 bug 往往需要通知维护人员进行修改发布,阻塞开发进度
  1. Monorepo 将所有代码保留在一个 repo 中,可以在项目之间共享代码,而无需维护多个存储库并。Monorepos 强制要求,不仅共享组件驻留在单个存储库中,而且消耗共享组件的项目也应驻留.而且重构成本较高。

为什么选用 bit

  1. 共享现有项目中已经开发的组件。
  2. 无需花费很长时间维护 UI 组件库。
  3. 支持项目中的二次开发。
  4. 可以保留使用项目中组件的本地修改,并且仍与传入的更新合并。
  5. 每一个组件就是一个包,无需等到大版本升级,可单独对现有功能就行修复和升级。

新版 bit 使用流程

介绍

Bit is a component-based approach to modern application development. Bit makes the development and composition of modern applications from independent components repeatable and fun.

官网地址


安装

  1. 安装 bvm 类似于 nvm 的 bit 版本管理工具
npm i -g bvm
  1. 安装 bit 使用 bvm 安装 bit
bvm install

安装成功后,运行bit -v看 bit 是否安装成功

参考链接: harmony-docs.bit.dev/getting-sta…

使用

初始化工作区

bit init --harmony

添加远程工作区

bit remote add http://xx.xx.x.x:port

新创建组件

  1. bit 支持使用 create 命令来创建新的组件
bit create react-component ui/button

上面命令创建了一个 button 的 ui 组件,其中 react-component 为 bit 创建组件模版的一个类型,可以通过bit templates命令来查看现在的模版。同时模版支持自定义,可点击文档查看具体操作。

ui/button 为 scope/name 就是组件当前所在范围以及组件的名称,便于分类。

新创建的组件的目录结构为

my-component
├── index.ts //入口文件,导出组件
├── my-component.compositions.tsx //使用该组件的示例
├── my-component.docs.jsx //文档
└── my-component.ts //组件的实现
  1. 待开发完成后,可执行
bit tag --all

来给所有新创建或者有修改的组件标记版本,也可以单独给某一个组件标记版本

bit tag <component-id> <new-version-number>
  1. 导出到远程工作区
bit export

在导出的同时可以同步发布到 npm 上,在项目中使用该组件的时侯用 npm 包的形式引入

在已有项目中导出组件

在已有项目中导出组件,大致流程与上述过程差不多,区别在于不再需要创建组件,直接使用

bit add src/xxx/xxx -n xxx

使用bit add命令可以追踪已存在组件, -nnamespace缩写。

注意: 使用 bit add 添加追踪组件后,如果在该文件夹下添加文件,新添加的文件将不触发本地调试的热更新,需要重新执行 bit add 命令,追踪新添加文件

其余操作与上述一致。

由于 bit 使用的包管理工具为 pnpm/yarn 2, 所以不建议在项目中使用bit import命令,在不同项目中导出组件后,在一个项目里统一存储这些组件,一是统一管理,二是存备份

关于webpack自定义修改

由于antd按需加载以及项目中使用yarn v1存在一些依赖提升的问题,需要在用到 antd 的地方添加 webpack 自定义配置。 代码如下:

import { WebpackConfigTransformer, WebpackConfigMutator, WebpackConfigTransformContext } from '@teambit/webpack';
const path = require('path');
const fs = require('fs');

// Make sure any symlinks in the project folder are resolved:
// https://github.com/facebook/create-react-app/issues/637
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
/**
 * Transformation to apply for both preview and dev server
 * @description It's ugly but useful
 * @param config
 * @param context
 */
function commonTransformation(config: WebpackConfigMutator, context: WebpackConfigTransformContext) {
    // Merge config with the webpack-config.js file - adding handlebars support
    config.addResolve({
        modules: ['node_modules', resolveApp('node_modules')],
    });
    // @ts-ignore
    const oneOfRules = config.raw.module.rules.find((rule) => !!rule.oneOf);
    // @ts-ignore
    const lessRule = findLessRule(oneOfRules.oneOf);
    // @ts-ignore
    const lessLoader = lessRule.use.find((loader) => loader.loader.includes('less'));
    // @ts-ignore
    lessLoader.options['lessOptions'] = {
        javascriptEnabled: true,
        math: 'always',
    };
    return config;
}

/**
 * Transformation for the preview only
 * @param config
 * @param context
 * @returns
 */
export const previewConfigTransformer: WebpackConfigTransformer = (config: WebpackConfigMutator, context: WebpackConfigTransformContext) => {
    const newConfig = commonTransformation(config, context);
    return newConfig;
};

/**
 * Transformation for the dev server only
 * @param config
 * @param context
 * @returns
 */
export const devServerConfigTransformer: WebpackConfigTransformer = (config: WebpackConfigMutator, context: WebpackConfigTransformContext) => {
    const newConfig = commonTransformation(config, context);
    return newConfig;
};

function findLessRule(rules: Array<any>, testMatcher = `/(?<!\\.module)\\.less$/`) {
    return rules.find((rule) => {
        return rule.test && rule.test.toString() === testMatcher;
    });
}

主要是添加 less 按需加载时候,需要开启 lessOptions 的javascriptEnabled,还有因为依赖提升,导致包找不到所以要手动配置寻找路径

config.addResolve({
    modules: ['node_modules', resolveApp('node_modules')],
});

统一管理

新开发的组件和从其他已有项目中导出的组件,统一放到一个项目里面管理,这个项目可以使用bit import的方式,从远程拉去所有的 bit 组件。如果后续组件需要修改的话,可以在这个项目中修改,然后重新发布到远程工作区。同时也留一份备份在 git 上,不会对已有组件丢失。这个管理项目可以采用 pnpm 的方式进行依赖安装。