从头开始创建 vanilla.js Web 组件工具链

多年以来,我一直在使用非常精简的工具链(主要由 TypeScript 和 jsdom 组成)开发原始 Web 组件,这是一项正在进行的实验。**目标**:在运行时,不依赖任何东西,并利用概念所发挥的 Web 组件属性:尽可能小、无状态的元素。

概括起来,这似乎很简单:编写 TypeScript 代码,将其转换为 JavaScript,然后“获利”。理论上如此。此外,还涉及打包器、编译器和 tree shake。供应商锁定很容易让您陷入困境。只需回顾过去 2 年中刚刚发布的更新,并将此信息作为未来更新的预测。这种方法可能并不总是能产生积极的结果。在我看来,许多软件系统组件(包括非常基本的 UI 元素)应该具有单独且更无聊的更新生命周期。并非所有 Web 前端(例如边缘设备上的配置 UI)都易于更新。

Web 组件规范的目的不是取代框架,而是提供各种现成的元素以减少对框架的依赖。Web 组件仅解决 React、Angular 和其他框架也试图解决的一组特定问题,尽管这样做的代价是局限于这些框架的开发流程、通用习惯用法和职业道路。简而言之:当您的 UX 团队发布基于 Tailwind 和 React 的 Web 组件目录时,使用其他框架甚至纯 HTML 都会变得更加困难。

为什么要重新发明轮子?

每当我采用一个新的现代框架时,它似乎都是现有事物的不同组合,各种包层在包上构建,并添加其他抽象层。我不介意软件中的抽象;在一定程度上,它让生活变得轻松。然而,当我对当前标准的理解由于信息的抽象而停滞不前时,我发现很难对信息架构做出明智的决定。接口是一切的基础,这就是它们如此重要的原因。

如今的工具链带有依赖关系树,在我看来,它有点太大了。这带来了巨大的维护挑战:框架发展迅速,频繁发布更新,在生产环境中运行时,不断需要更多依赖关系和更新可能会带来负担。我想了解这些框架为什么如此“沉重”。

然后,我对打包器很反感:TypeScript 已经存在用于简单的无状态组件(如“打包”、“摇树”和方法)的功能,它主要解决与依赖 SPA 模式相关的问题。我知道这会大大减少我可以使用的功能,但我准备承担后果并恢复理智。

我也想避开运行时组件。运行时组件会对最终用户端产生依赖,我更愿意避免这种情况。最终,维护它是项目的责任。让我们看看没有它我能走多远。

基本规则。

这不是演习:UHU(100 以下)规则适用:我们保持在运行 TDD 循环所需工具的依赖限制之下。此限制迫使我们要么构建某些功能,要么排除其他功能。此限制将阻止我仅为了浏览第三方界面而开发过于广泛的功能集。

我想专注于 TypeScript 并进一步研究其功能。通常,我们使用 TypeScript 时不会考虑太多,只是对其进行配置直到它正常工作。事实证明,它功能丰富,并且文档非常非常完善。

JSODM 是我选择的组件测试环境。Web 组件标准的实施仍在讨论中,我想它仍在不断进步。该方法有理论上的局限性,但我想看看我能把它推到多远。

Node 已经提供了测试工具,我也想进一步探索一下。性能已经达到了应有的水平,到目前为止,我使用它非常高效。最后,我想构建一堆没有运行时依赖关系的 vanilla.js Web 组件,并在构建过程中使用工具。能够一次性更改组件的源代码并针对模拟 DOM 进行清晰的 TDD 循环应该是可行的。

体验

感谢 Windsurf.Idea:大约花了 40 个小时才将项目带到目前的状态。Windsurf 确实有助于重构和对代码库进行“主观更改”。我首先想到将 Web 组件安装到 JSDOM 对象,这样就可以在 RAM 中安装组件。该过程的另一个方面涉及使用 TypeScript。在将 TypeScript 源文件安装到 JSDOM 之前,我仍然需要将其转换为正确的 JavaScript。我开始尝试使用 TS 编译器,发现可以在安装组件时进行编译。但速度很慢。现在所有实际问题都出现了:如果对多个组件进行多次测试怎么办?好吧,有缓存(我还没有尝试过)或内存文件系统可以加快构建时间。

null

整个工作也有一个文档角度。将组件变成一个工作演示应该很简单——最好只使用组件源代码中的文档标记。TSDOC 是一个有用的工具,可以连接到 TypeScript 文档解析并添加您自己的标记。最后,真正的兔子洞开始打开:创建一个小型工作工具链,支持我构建一堆不简单但仍然有意义的原始 Web 组件。

经过一番研究,我发现音频 Web 组件这个主题非常有趣:它涉及大量数学知识,并且有许多示例可以说明技术、时代和其他技术因素的各个方面。Web MIDI 在提供可配置所有类型音频设备的可行平台方面确实取得了成功,用例也证明了这一点。现在,我将评估使用开发的工具可以建立组件基础的程度。

结果

我非常有信心 Windsurf.ai 或其他以同样方式构建的工具可以帮助我未来的努力。早期的 CodePilot 和 ChatGPT 是我最后一次尝试的主要动机,而 Windsurf 感觉像是一次真正的升级。这个月我已经使用了 40% 的积分,结果是值得的。我不是那种轻易称赞 GenML 工具的人,但就 Windsurf 而言,我确实从这个工具中学到了很多东西。与 LLM 聊天和代码库的交互令人满意,为我提供了充足的时间来审查规范、做出明智的决定,并在处理项目时将大量新信息存储在我的湿件中。

代码库的简约设计十分引人注目。事实上,主 TDD 循环的工具依赖项少于 100 个,而且似乎还包含文档生成。这主要涉及使用 commander.js、TypeScript、TypeDoc 和 memfs。

使用内存文件系统进行 TypeScript 编译并加快所有程序速度是一项重大挑战。我预计通过在测试执行期间缓存结果可以进一步缩短构建时间。

CLI 应用程序可以交付底层框架。单元测试涵盖了大多数 (c) 类,尽管更改很复杂,但感觉却毫不费力。讽刺的是,我正在现有工具上构建另一层以简化开发。

链接

  • 本文中描述的代码库
  • Typescript 虚拟文件系统
  • 节点测试
  • Typescript Transformer 手册
  • TSDoc 解析器
  • 内存文件系统
  • Codeium 风帆冲浪