桶形锉刀以及为什么你应该立即停止使用它们
一些小决策也可能对应用程序产生重大影响。当开发人员开始使用桶文件时,它们可能看起来像是一种无害的模式,但事实并非如此。
[更新于 2024 年 3 月 23 日]:
继续阅读前请注意:本文及其指标均基于最终的前端应用程序而创建。最终用户浏览的那些应用程序,例如 dev.to 和我的源项目。因此,如果您在其他任何环境中(例如软件包)使用过 Barrel 文件,那么它(Barrel 文件)可能符合您的预期。请查看@kasper573的精彩评论。
什么是桶形锉?
桶文件是一种简单的导出模式,允许开发人员从唯一路径导入不同的文件。
让我们看一个例子:
// ./barrelFiles/used.ts
export const HEY = 'hey used';
// ./barrelFiles/notUsed.ts
export const HEY_NOT_USED = 'hey NOT used';
// ./barrelFiles/index.ts
export { HEY_NOT_USED } from './notUsed';
export { HEY } from './used';
/*
This is a barrel file, which will be used as a unique path to import any files into barrelFiles folder (such as ./used).
*/
使用方法:
// ./Component.tsx
import { HEY } from './barrelFiles'; // instead of use './barrelFiles/used'
乍一看,这看起来很棒,不是吗?这的确是开发经验,但成本很高!
应用程序包中的 Barrel 文件费用是多少?
关于桶文件,你必须记住一个关键问题:当我使用桶文件里的内容时,会导入什么?它只导入我用到的内容吗?
我们来看一些例子。好的,我们在 barrel 文件中添加两个文件,并添加一些 console.log 来查看它们是如何工作的:
// now there are 4 files in barrelFiles folder
// ./barrelFiles/used.ts
export const HEY = 'hey used';
console.log('%c Im used xD', 'color: green;');
// ./barrelFiles/notUsed.ts
export const HEY_NOT_USED = 'hey NOT used';
console.log('%c WAIT! Im NOT used', 'color: red');
// ./barrelFiles/notUsed1.ts
export const HEY_NOT_USED_1 = 'hey NOT used 1';
console.log('%c WAIT! Im NOT used 1', 'color: red');
// ./barrelFiles/notUsed2.ts
export const HEY_NOT_USED_2 = 'hey NOT used 2';
console.log('%c WAIT! Im NOT used 2', 'color: red');
还有桶文件:
// ./barrelFiles/index.ts
export { HEY_NOT_USED } from './notUsed';
export { HEY_NOT_USED_2 } from './notUsed2';
export { HEY_NOT_USED_1 } from './notUsed1';
export { HEY } from './used';
好吧,回到问题本身,如果我导入HEY,我预期只会导入./used文件内容。因此,让我们通过将其导入到我的个人项目中来实现这一点,在那里你可以找到更多类似的文章:
// ./Component.tsx
import { HEY } from './barrelFiles'; // I wanna use HEY, only
你看到了吗?即使只使用了HEY,它也显示了所有 console.log,这意味着所有文件都已导入。
现在,不从桶文件导入。
// ./Component.tsx
import { HEY } from './barrelFiles/used'; // I wanna use HEY, only
直接导入一个console.log就显示出来。
你可能会疑惑:为什么我的项目中会有未使用的文件?
这个问题问得好。我来谈谈几点:
- 在这个例子中,文件很少,但如果一个大型项目使用了十几个 barrel 文件呢?很可能其中会有一些未使用的文件。如果你使用的是 monorepo,它可能包含许多应用程序使用的共享文件夹。创建一些模式来避免团队成员(以及你)犯错,是作为开发人员你能做的最好的事情;
- 尽管 Vite 和 Webpack 等工具可以优化打包并避免使用重复导入的块,但确保尽可能优化的更好方法是了解应用程序的工作原理。为了理解这一点,请参见以下屏幕截图。
现在让我们看看捆绑包的差异(请注意,由于这是一个教学示例,所以差异很小。请放大它以了解其影响)。请参阅此评论,其中包含实际数字。
可以看到,最终的 bundle 大小有所差异。由于没有使用 barrel 文件,最终的 bundle 大小更小。
循环依赖是桶文件的另一个问题。
喜欢吗?如果喜欢,别忘了点个赞❤️_ 并关注我获取最新资讯。之后我会继续创作更多类似的内容_
单元测试的 Barrel 文件成本是多少?
一旦 Vitest 和 Jest 等单元测试引擎不再像 Vite 和 Webpack 那样关心 bundle 优化,单元测试中的 barrel 文件就更糟糕了。让我们通过创建两个只使用 HEY 的助手来看一下。
// ./helper.ts
import { HEY } from './barrelFiles';
export const helper = () => {
console.log(HEY);
};
// ./helper2.ts
import { HEY } from './barrelFiles';
export const helper2 = () => {
console.log(HEY);
};
现在将它们导入到测试文件中
// ./helper.epec.ts
import { describe, it } from 'vitest';
import { helper } from './helper';
describe('helper', () => {
it('Should only use HEY', () => {
helper();
});
});
// ./helper2.epec.ts
import { describe, it } from 'vitest';
import { helper2 } from './helper2';
describe('helper2', () => {
it('Should only use HEY', () => {
helper2();
});
});
如你所见,项目里有一堆未使用的 console.log 文件,而且每个使用 barrel 文件的测试文件,甚至使用过 barrel 文件的文件,都会出现这种情况。你能想象这会对性能造成什么影响吗?嗯……太可怕了。
现在,删除桶文件
测试时不使用 barrel 文件:1.32 秒

请我喝杯咖啡☕。希望我能帮到你。🤗
奖励(自动更改导入语句)
[2024年7月4日更新]:
查看此脚本以自动更改导入语句。它将帮助您删除 barrel 文件。
[2024 年 7 月 17 日更新]:
另外,请查看 Eslint 插件eslint-plugin-no-barrel-files以避免出现 barrel 文件。
[2025 年 3 月 18 日更新]:你更喜欢命令行界面 (CLI) 吗?来看看这个由Nergie提供支持的强大命令行界面吧。
结论
[2024 年 3 月 23 日更新]:
在本文中,您了解了有关桶文件模式及其对最终前端应用程序的影响的更多信息。
正如我之前所说:创建一些模式来避免团队成员(以及你自己)犯错,是作为开发者你能做的最好的事情。这对于不使用桶文件的情况同样适用:
- 减少最终的捆绑包和避免导入东西是不被采用的;
- 提高单元测试性能;
昂贵的。
文章来源:https://dev.to/tassiofront/barrel-files-and-why-you-should-stop-using-them-now-bc4