Skip to content
On this page

Barrel

Barrel 就像是一个容器,它的作用是把分散在多个模块的导出合并到一个模块里导出。一般来说,barrel 本身就是一个包含模块的文件,这个模块做的就是重新导出其他(多个)模块导出的东西。

想象一下,在一个库中,具有如下结构的类。

ts
// demo/foo.ts
export class Foo {}

// demo/bar.ts
export class Bar {}

// demo/baz.ts
export class Baz {}

如果不用 barrel,那么用户在引入时就需要三条 import 语句:

ts
import { Foo } from '../demo/foo';
import { Bar } from '../demo/bar';
import { Baz } from '../demo/baz';

但如果我们在同级添加 barrel 文件 demo/index.ts,然后这样定义它:

ts
// demo/index.ts
export * from './foo'; // 重新导出 foo 导出的东西
export * from './bar'; // 重新导出 bar 导出的东西
export * from './baz'; // 重新导出 baz 导出的东西

现在,用户就可以直接用一条 import 语句从 barrel file 导入所有东西:

ts
import { Foo, Bar, Baz } from '../demo'; // ../demo,会自动解析成 ../demo/index.ts

命名导出

除了使用通配符 * 导出模块中的所有东西,我们也可以选择要导出什么以及如何导出。试想一个存在多个函数的 baz.ts

ts
// demo/foo.ts
export class Foo {}

// demo/bar.ts
export class Bar {}

// demo/baz.ts
export function getBaz() {}
export function setBaz() {}

如果不想在 demo 模块上直接提供 getBazsetBaz 接口,你可以把它们挂载到一个变量下。你需要做的只是在 barrel file 里导入全部并命名,然后导出命名后的名称即可。

ts
// demo/index.ts
export * from './foo'; // 重新导出 foo 导出的东西
export * from './bar'; // 重新导出 bar 导出的东西

import * as baz from './baz'; // 导入 baz 中所有的东西,并命名为 baz
export { baz }; // 导出命名后的名称

现在,用户需要这样调用:

ts
import { Foo, Bar, baz } from '../demo'; // ../demo,会自动解析成 ../demo/index.ts

// 使用
baz.getBaz();
baz.setBaz();
// ……
Barrel has loaded