一致:UI 设计系统
为了保证一致的界面外观,建立一个通用的设计系统是明智的。
通常一个稍大一点的公司都会有自己的 UI 设计系统,及对应的技术组件库。搭建一个优秀的设计系统将花费不少时间,但这能让我们中长期受益:一致性、通用术语、开发速度、规模化。
设计系统像篝火,让来自不同团队、不同领域的人们经常围绕着它讨论来讨论去
设计系统永远不是成品,最好将其视为一种过程。很多设计系统一开始精心制作,后续没有人维护迭代时,设计系统开始无法满足要求,团队只能通过覆盖组件样式来满足他们的需求,这时情况会迅速恶化,成为僵尸系统。应该为设计系统专门制定人力资源维护,不断丰富组件、审视现有设计、重构、完善文档、提升一致性。
在微前端架构下,各团队要使用一致的设计系统并不容易。首先是开发流程的问题:
开发流程:集中模式与联合模式
集中模式:设立一个专门的团队,负责规划和开发设计系统,提供给产品开发团队使用。产品开发团队只是设计系统的用户,中心化的设计团队很可能成为瓶颈,不能满足所有开发团队的诉求。
联合模式:每个产品开发团队都可以参与到设计系统的开发中,由设计师和负责人来把控质量及一致性。
集中模式和联合模式并非非此即彼,而是可以互相结合。通常来说,在搭建阶段更适合集中模式,在稳定迭代阶段更适合联合模式。
在微前端架构下,第二个问题是技术层面上如何整合设计系统与应用:
运行时整合和构建时整合
运行时整合:组件库的所有资源(js、css、icon 等)在全局引入(script、link 标签等方式),跨团队分发。
这种方式设计系统能快速同步到各团队,设置起来非常简单。
但是会带来相当严重的耦合,对团队自治性有一定的破坏。
- 沙盒测试——微前端应该是自包含的,运行时整合使得各团队无法控制设计系统,必须运行自动化测试来验证产品是否正常
- 单点故障——所有团队都依赖样式库,任何一点疏漏都可能造成整个项目崩溃
- 无法使用 tree shaking 或者特性弃用
- 破坏性更改——不能避免破坏性修改,如果希望重构,只能创建新的组件,在其他团队更新完后删除老的组件
- 版本控制和命名空间——无法做到版本控制,不同微前端之间会互相污染样式
缺少版本控制是非常致命的问题,这意味着所有团队都必须使用最新版本组件库,需要各团队之间紧密合作并同时部署,令设计系统的开发团队畏首畏尾,不敢进行必要的改进。不过这个问题目前可以通过 importmap scope 缓解。
构建时整合:组件库以包的形式(npm)分发给各团队,每个团队在各自的产品中分别引用,是否更新取决于各团队。
这种方式有几种好处:
- 自包含——可以通过打包工具为组件库添加 css 前缀,很好地隔离 css。即使一个页面不同微前端使用不同版本组件库也不会互相影响
- 独立升级——产品开发团队可以根据自己的节奏更新组件库
- 剔除未使用代码——每个页面只打包使用到的组件
也存在几种缺陷:
- 冗余——用户在不同页面可能会下载很多相同代码
- 推广缓慢——组件库修改后要很长时间才能在所有微前端中更新完
- 一致性——页面上不同地方的同一组件可能会有不一样的表现
建议使用构建时整合。尤其是在后台系统中,冗余和不一致并不会造成很大问题。
在微前端架构下,第三个问题是如何决定哪些组件应该沉淀在公共组件库中:
组件应该写在公共组件库还是项目里
使用公共组件库是有成本的,相比之下在项目中维护一个组件要容易得多。使用公共组件的问题:
- 依赖——使用公共组件依赖外部,需要发布一个新版本并在项目中安装
- 其他团队——公共组件会被其他团队使用,需要考虑影响
- 质量标准高——公共组件被多团队使用,需要设计合理并便于理解
- 流程复杂——基于组件库的开发流程,需要进行严格的审核流程保证代码的高质量
组件应该写在公共组件库还是项目里,主要从组件复杂度和可复用性两个维度判断。
复杂度:简单的组件公用,而复杂的组件由团队自己控制。
复用性:如果多个团队都用到某一个组件,那么即使这个组件很复杂,也应该将其放在公共组件库中。
产品功能是经常变化的,以前适合放在公共组件库的组件今后也可能不再适用,在某个项目中的组件也可能未来沉淀在公共组件库中。这很正常 😄。