Bit 最佳实践 - 第三节:bit是如何处理组件之间的依赖的

2,226 阅读2分钟

源组件

设想我们的若干源组件【souce components】满足这样的目录结构关系,所有组件都仅仅通过一个 index.ts 向外暴露接口,相互之间仅通过 index.ts 引用依赖——这个是一个很重要的原则,isolate:

而这些源组件存在如下的依赖关系:

  • Zoo.tsx 通过 ../Camel 引用 Camel 组件,【Legacy Mode Relative Paths
  • Zoo.tsx 通过 @source/Elephant 别名引用了 Elephant 组件

依赖解析

通过 bit add src/source/zoo --id demo/zoo 对 Zoo 组件进行追踪,bit 会把组件目录、文件等相关信息会被写入到 .bitmap。

bit 会在执行 tag 时候才会解析组件的依赖,所以当 bit tag demo/zoo 时,会抛错,并同时打印两个告警信息:

  1. missing packages dependencies …… Elephant
  2. untracked file dependencies …… Camel

对于告警 1,我们需要在 bit.json 里配置别名,告诉 bit 如何去查找 @source 依赖:

    {
        "resolveModules": {
            "aliases": {
                "@source": "src/source"
            }
        }
    }

而告警 2 则需要 bit add、bit tag Camel & Elephant 两个组件:

bit add src/source/camel --id=demo/camel
bit add src/source/elephant --id=demo/elephant
bit tag demo/camel
bit tag demo/elephant

然后就可以再次 bit tag demo/zoo,并且成功—— bit 会把对 Camel、Elephant 组件的依赖映射为对 demo/camel 、demo/elephant 的依赖【Relative Source】——接下来就可以通过 bit export scopeName 导出组件。

依赖安装

更直观的体验一下,可以配置 bit.json:

{
    "env": {},
    "componentsDefaultDirectory": "components/{name}",
    "packageManager": "npm"
}

然后:

bit init;
bit remote add ssh://bit@你的私服:/data/bit/my-test;
bit import my-test/demo/zoo;

最终的 bit 创建目录树是这样的:

其中,components 目录下:

  • demo/zoo 保留了跟源组件相同目录结构:
    • Zoo 跟源组件内容一模一样的目录结构、源文件;
    • 创建 Camel 目录, 通过 index.ts 导出 camel,让 Zoo 可以找到相对路径依赖 Camel
    • 将 node_modules/@bit/* 软链至 .dependencies 下对应依赖的特定版本
    • 为让 Zoo 可以找到通过 @source 别名引入的依赖 Elephant,十分机智的创建了 node_modules/@source/Elephant 目录,并通过 index.js 和 index.d.ts 导出逻辑和类型——这就带来一个问题:

如果:

import Elephant from '@source/Elephant/Elephant';

但是在对应的 node_modules/@source/Elephant 并没有 Elephant.tsx,必然会是错误的——这就是为什么组件之间要 isolate,因为 bit 就这么限制了——奇怪的是这里为什么不把 Elephant 直接软链到 node_modules/@bit/my-test.demo.elephant?

  • .dependencies 下是 demo/zoo 各依赖组件的不同版本的源文件。

然后,node_modules/@bit 目录下会有软链到 components/demo/zoo 的 my-test.demo.zoo,这样在业务代码里就可以通过 @bit/my-test.demo.zoo 引入 Zoo 组件。

经验总结

组件之间 isolate——组件所有的成员,包括逻辑、类型都只能通过唯一的出口,比如 index.ts 导出;对其他组件依赖的引用,也必须通过该组件唯一的出口,进行引用。如此就可以避免踩到 bit 依赖处理这块的坑。