探讨 web-components 的正确使用姿势
web-components 是什么?
Web Components 是一组 Web 原生 API 的总称,允许开发人员创建可重用的自定义组件。
可以替代现代 UI 框架吗?
封装自定义元素,听着很熟悉,似乎解决了前端开发必须使用 vue
、 react
等 UI 框架来实现代码复用的问题。
但是在 2021 这个时间节点,我们使用 UI 框架已经不再是纯粹的为了组件复用
。我们更离不开的是声明式(数据驱动)的开发方式,以及 UI 框架的一系列周边带来的开发便捷。比如 vuex 做状态管理,vue-router 做路由管理等。
我们享受着 UI 框架带来的 现代式
开发,虽然他不是 web 标准,但是声明式的开发方式几乎已经成为了现代 web 前端的事实标准。
而 web components
可以看作只是丰富了 HTML 的原生标签。所以它无法和 vue
react
等做一个正面比较,更别说 web components
的出现会取代它们。
那么,它适用于什么样的场景?
UI 组件库!当你希望你的 UI 组件可以在任何框架上运行(包括原生),那么使用 web components
可以达到目的。
由于它只是拓展了 HTML 的原生标签,所以你可以像使用 div
标签一样的方式来使用它。这样可以拓展你的 UI 组件库的受众。无论开发者使用的是 vue
还是 react
都可以调用你的组件。(^_^ 当然包括原生开发)
以什么姿势使用为佳?
由于 web components
是一组原生的 API,所以它和原生一样,都属于命令式的开发方式。你需要使用 const Ele = document.createElement
来创建元素。当状态改变时,你还不能忘了 Ele.value = xxx
来更新视图。
想想都很恐怖,一夜回到解放前。如果是稍微复杂一点的组件,代码量将直线上升,且导致代码的可维护性降低。
所以我们希望既可以享受到 web components
通用性,又能享受高效的声明式开发。
vue3
推出了一个解决方案 —— definecustomelement。你可以使用 vue
的方式去封装组件,再通过 definecustomelement
转换成 web components
。
关于这个话题,我觉得 vue 官网已经说得非常好了,不画蛇添足。官方说明
逼逼了这么久,我想说什么?
我们编辑器的 UI kit
选择了 web components
作为载体是非常明智的选择。这样给与了开发者最大的自由,它们可以任意的选择自己合适的 UI 框架。
但是 UI kit
是以原生的方式去开发的。我们让广大开发者爽了,但是却没让自己爽起来。我一直坚信,能服务大众的前提一定是先服务好自己。
所以我提议:以 web components
的方式去暴露组件,但是组件内部仍然以声明式的方式去书写。
好处:
- 代码维护性更强
- 开发效率更高
问题:
- 带来一点 vue 的运行时开销
- 依赖了 vue
我尝试反驳一下以上两个问题。
运行时开销
在性能问题没出现之前,说性能都是伪命题。
在 JQ 时代,也有人说,要使用原生 js。因为 JQ 会导致包体变大,然后踏上了原生的道路。接着发现很多 utils 需要封装,就特别有成就感的封装了自己的工具库,不断组合。最后发现,自己的工具库大过了 JQ,且 API 设计还不如或者仅次于 JQ 的优雅。舍弃了巨人的肩膀,又朝着巨人的方向前进。
以上例子纯属虚构!
依赖了 vue
情绪激昂的说:如果依赖 vue 会成一个问题,那么 vue 应该不会发展到 3.0。
慢条斯理的说:Vue 是 MIT 开源协议,所有源码公开。且全世界都在使用,经过无数实际项目验证的。我个人是找不出拒绝的理由。
2024 年 7 月补充
ui-kit 的定位是时间跨度需要长达 10 年以上,所以选择了面向浏览器的标准提供组件,选择了 web-component,抛弃了具有更好开发体验的 vue react 等框架。我也赞成这样的决定。它还有个更好的好处是可以适应所有 前端框架
但是在编写原生 web-component 的时候,只能是命令式的语法,这样的结果就是一个组件你有更多的关注点,数据和 dom 表现。导致的结果就是 bug 变多。
可维护变差也是不争的事实,除非能保证团队里所有人员都是编程高手,代码风格趋向统一,否则命令式的写法在多人协作上,就是一种增煽。这也是为什么 vue 的 options 式开发对多人协作是很友好的,不管水平高低,写出的组件基本是趋同的,因为组件强行区分了 data computed methods 和各种钩子,这种填鸭式的编程是有极大好处的 ,特别是多人协作。代码趋同是一个团队的福音。
回到编辑器目前的真实现状,就是每个接手 ui-kit 的人,看代码的过程都很痛苦,而且修 bug 的上手时间也更久。
如果引入 lit,首先它不是框架,是一个定位非常聚焦的库,只为 web-componet 服务,让装组件可以享受声明式的语法。
团队目前最大的质疑是对 lit 的不确定性,慎重是合理的,但是不能固执,首先 lit 的开发团队是谷歌背书的,这点在专业性上应该不用质疑,而且周下载量也非常大。
photoshop 在开发 web 版本的时候,也是选用了 lit 来构建他们的 web-component ,具体可以看 Photoshop is now on the web!
Enabled by WebAssembly + Emscripten, Web Components + Lit, Service Workers + Workbox & new Web APIs. Chrome & Adobe enjoyed collaborating on it.
所以引入 lit 带来的好处如下:
- 声明式语法替代命令式语法,代码逻辑更清晰,关注点减少
- 代码量减少
- 按照 lit 的模式开发,代码格式会趋同,对于团队的多人协作比较友好。
- 构建更简单,lit 一切都是 js, html 和 css 都是以 js 的形式提供,所以整个组件库的构建流程可以非常简单,甚至 tsc 即可。
缺点:
- 我们依赖了一个外部库,万一有 bug,在处理 bug 上可能不太可控,你需要等官方修复。
- 万一 10 年后不维护了,怎么办。
其实以上两点如果很担忧,那么你一定非常害怕看到项目的 package.json 的 dependence,我们是否也应该抛弃 vue 和 electron。
...