如何处理Svelte自定义元素的交叉依赖关系以及“ CustomElementRegistry”上的“ define”执行失败

问题描述

上下文:我们正在构建svelte UI组件库作为自定义元素,以便在多个新旧应用程序中使用。所有组件都作为软件包存在于monorepo中,并且可以自行维护和交付。

目标:提供小型通用js程序包,这些程序包可以临时使用,而消费者的开销却最小。

情况:

  • 存在一个简单的(原子)自定义元素,例如our-button
  • 存在另一个更复杂的自定义元素our-modal,该元素使用(导入)our-button

如果消费者带来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 —免责声明:我写的是–允许您甚至在很少的不支持本机的浏览器中使用本机模块。)