我可以有条件地导入和重新导出JS库吗



我一直在努力寻找一个好的模式来分割我的代码,因为我目前正在捆绑每个React组件的N个版本,并且每次只使用一个。

当前模式为

import {
Component1 as Component1_Lib1,
Component2 as Component2_Lib1,
} from 'lib1';
import {
Component1 as Component1_Lib2,
Component2 as Component2_Lib2,
} from 'lib2';
export const SiteSpecificComponent1 = (site) => {
return {
site1: Component1_Lib1,
site2: Component1_Lib2
}[site]
};

等等。

然后在站点之间共享的各种组件中使用这些组件。捆绑包将始终包括每个组件的所有版本。

我一直在尝试设计一种模式来干净地将其分割开来。我已经研究了懒惰加载和有条件导入,但我还没有想出任何东西,所以我来找你。是否有您熟悉的构建技巧或架构模式可以帮助我从捆绑包中分离未使用的组件?

谢谢你的帮助。

理想情况下,您应该依靠Tree shaking来完成它的工作,以便只捆绑所需的组件。然而,成功的摇树取决于两个因素:

  • 将您的库发布为ESM模块。(使用package.json文件中的type: "module"或使用*.mjs文件)
  • 使用sideEffects声明包没有副作用(您的模块实际上应该没有像singleton、在模块顶部使用全局窗口对象等副作用)

然而,这还不够。以下代码的存在将不允许树抖动正常工作,因为Webpack/Rollup无法计算出site在编译时的值。这意味着它最终会拾取捆绑代码中的所有内容。

export const SiteSpecificComponent1 = (site) => {
return ({
site1: Component1_Lib1,
site2: Component1_Lib2
})[site];
};

为了解决这个问题,我们需要对您的网站进行假设。如果这些不同版本的组件要在不同的站点/应用程序中使用,那么这可能意味着该应用程序将具有单独的构建脚本和单独的存储库。现在,如果您使用的是最新的技术堆栈-Node 16、Webpack 5、TypeScritp 4.5、Jest 28,那么您可以使用支持子模块或子路径导出的新package.jsonexports字段。您的package.json将看起来像:

// package.json file
{
"name": "your-lib-name",
"type": "module",
"exports": {
"site1": "./dist/site1.js",
"site2": "./dist/site2.js"
}
}

在每个文件中,只导出属于特定站点或应用程序的组件。例如,

// site1.js
export { Component1 as Component1_Lib1 } from 'lib1';
export { Component1 as Component1_Lib2 } from 'lib2';
// site2.js
export { Component2 as Component2_Lib1 } from 'lib1';
export { Component2 as Component2_Lib2 } from 'lib2';

// Usage
import { Component1_Lib1 } from 'you-lib-name/site1.js';
import { Component2_Lib1 } from 'you-lib-name/site2.js';

当然,您失去了使用方法调用动态获取组件名称的能力,但这更适合捆绑包,因为它很容易进行树摇。

最新更新