问题描述
上下文:我们正在构建svelte UI组件库作为自定义元素,以便在多个新旧应用程序中使用。所有组件都作为软件包存在于monorepo中,并且可以自行维护和交付。
目标:提供小型通用js程序包,这些程序包可以临时使用,而消费者的开销却最小。
情况:
如果消费者带来our-button-bundle.js
以便在一个地方使用 our-modal-bundle.js
,则our-button
的重复会导致:
Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name "our-button" has already been used with this registry
更不用说,这是两次为button输入代码,这很膨胀。
为什么不使用构建工具...?理想情况下,我们希望消费者在这里几乎不松手。支持的应用程序包括WebForms,ASP .NET等。作为一个ui团队,我们只希望他们指向一些js捆绑包,然后开展业务。我们维护并推动,他们导入并实施。 (嘿,一个团队至少可以梦想...)
到目前为止可能的选择:
-
all.bundle.js
没有重复的代码或名称,但 Bloated 。对不起,最终用户,无论应用程序使用一个还是多个,您都会获得整个库。 - 一个
core.bundle.js
或常见的小型可重用元素(类似于vendor),另一个是较大分子的类似组件。我看不到这将如何工作。使用自定义元素-如何在没有按钮的情况下预编译模态编译?如何在开发模式下工作? - 围绕自定义元素定义的运行时脚本,例如:
if (!window[MY_ELEMENT_NAME]) {
// register...
} else {
return;
}
同样,此选项将通过网络发送重复的代码,尽管只应注册和使用该元素的一个实例。
我们也永远不会在组件之间导入任何共享模块,但是我觉得这违背了组件的全部目的。
欢迎针对这种情况的体系结构提出任何建议。
解决方法
简短的答案是,您需要将组件作为单独的模块分发,这样当某人导入our-button
并随后导入our-modal
时,our-modal
使用{{1}的副本}已在模块注册表中。
这确实意味着每个(顶层)元素都需要自己导入,并且与分发较粗的包相比,浏览器将必须下载更多的模块,但是消费者可以选择创建自己的包
({Shimport —免责声明:我写的是–允许您甚至在很少的不支持本机的浏览器中使用本机模块。)