本文档主要描述 EE NEXT SDK 团队使用 Web Component 开发前端组件的技术决策,并穿插一些 Web Component 技术标准如 CustomElement、Shadow DOM 的优缺点介绍和踩坑经验。
EE NEXT SDK 是字节跳动 - 效率工程 - 中台前端团队开发的一款功能性前端业务组件合集,它能够将效率工程中台团队的 AI 搜索、员工信息查询、AI 信息增强等能力以前端组件形式对外输出。
EE NEXT SDK 包含诸如搜索、员工卡片以及知识卡片等多个具有配套后端服务的前端业务组件,只提供 CDN 接入方式,因此业务线在使用 SDK 时通常会以如下形式接入。
<!document>
<head>
<script async src="https://{{cdn-host}}/{{cdn-path}}/user-card-v1.0.0.js"></script>
</head>
Web Component 是 W3C 支持的前端组件开发规范,包含 CustomElement、Shadow DOM、Slot 以及 HTML Template 等标准 API 和特性。
Web Component 能让前端开发人员实现跨技术栈和跨浏览器使用的前端组件,目前市面上占有率较高的浏览器均支持这一特性。
Web Component 的跨端和跨技术栈特性,以及天然的样式隔离,能够解决长久以来中台前端组件存在的通病:
只能工作在 React16 技术栈
容易被业务环境样式污染
用起来麻烦
NEXT SDK 团队需要开发一款新的员工卡片前端组件,用于展示公司 / 组织内的人员信息如姓名、邮箱和工作城市等。
开发新员工卡片需要应对的几个问题:
跨技术栈和跨端使用
员工卡片会被多个商业化应用如飞书招聘、飞书 OKR 等集成,不同业务线可能使用 React15、React16 甚至 Vue.js 作为技术栈。
为了能够适应不同业务环境的技术栈,甚至于浏览器端、WebView 等环境也需要适配,新员工卡片的技术体系需要具备高兼容性。
组件编译体积要尽可能小
作为一款第三方 SDK,NEXT SDK 里的每一款组件都是一个单独的 JavaScript 文件,因此对组件文件大小提出了较高的要求,应尽量避免体积过大带来加载时间长的问题。
样式保护
如果无法做到组件自身的样式保护,势必会被不同业务环境的样式所影响,导致反复出现组件展示错误,造成不必要的返工。
易用性
新员工卡片技术体系需要实现组件化,以降低用户的使用成本,组件的声明、实例化、卸载以及副作用的管理都不是也不应该是业务线 RD 所关心的。
不侵入业务开发环境
不需要业务线 RD 修改自身项目构建流程,完全解耦
受应用场景限制,使用 React 开发组件会遇到如下几个问题:
仅能工作在 React 高版本应用中,若要在低版本 React 或 Vue.js 场景中使用,则需要投入额外的研发成本单独开发,开发成本和维护成本变高
受 EE NEXT SDK 集成方式限制(CDN 接入),员工卡片组件代码打包体积不能过大,否则会因加载时间过长而导致组件生效滞后。一般情况下,React 体系的 runtime 均比较大,所以在体积控制上并不是特别理想。
在进行纯 React 组件开发时,若要实现样式隔离或样式保护效果,通常会选择许多 css-in-js 方案如 emotion 。早期时,EE NEXT SDK 团队大量采用了 emotion 来保证组件样式不会被业务系统样式污染,但常常引入意料不到的样式泄露问题,最终放弃了继续使用该工具。
1 . 兼容性高。作为浏览器原生支持的技术标准,使用 Web Component 开发的前端组件天然能够无视技术栈和浏览器等差异,在大多数环境下均能正常使用。
2 . 体积小。Web Component 不需要像 React.js 、Vue.js 和 jQuery 等引入大体积 Runtime 文件,所有组件的声明、实例化和销毁均由浏览器负责,能够使得最终编译体积足够小。
3 . 样式隔离。Web Component 体系下的 Shadow DOM 能为组件元素提供天然的样式保护,Shadow DOM 下的子元素不会被外部样式选中,也不会受到外部 JavaScript 影响,最大程度降低了出现样式问题的概率。
4 . 使用简单。使用 Web Component 开发的组件可如普通 HTMLElement 元素一样使用,无需特殊处理,使用起来与日常操作 DOM API 较为接近。
5 . 稳健性高。尤其是在微前端架构下具有明显的优势,不会因为子应用频繁切换、元素重建和销毁造成 Web Component 组件出现副作用卸载不及时或组件无法重新挂载问题。
Web Component 开发离不开 CustomElement 和 Shadow DOM 两大主力,下面将对这两个概念进行简单介绍。
以下内容将用 CodeSandbox 演示 Web Component 组件简单开发流程,流程包括 CustomElement 和 Shadow DOM 使用,主要开发内容为:
新建一个 custom-
button,实现简单的按钮元素
使用 Shadow DOM 将组件内容封装起来,避免被外部样式影响
核心步骤
使用 ES6 Class 定义一个 CustomButton 组件
使用 customElements.define
注册上述组件,注册后便能够直接使用
在入口文件中使用定义的 CustomButton 组件
使用 DOM API 创建一个 CustomButton 实例并插入 DOM 节点中
核心步骤
1 . 在 custom-button 下挂载一个 Shadow Root
2 . 在 Shadow Root 内添加一个样式表,使其能够影响 Shadow DOM 内元素,同时不影响外部
https://codepen.io/weidongxin/pen/MWmNgOb
CustomElement 能够让开发者快速地创建可复用的 Web 前端组件,并能够如操作普通 HTMLElement 元素一样,新增、修改和销毁组件。
CustomElement 定义的组件可在任何支持这一特性的浏览器或 WebView 中使用。
不引入额外的 Runtime ,组件文件体积可以控制得很小。
生命周期完备,利用生命周期能够方便地在组件内创建、管理和销毁副作用,减少 OOM 风险。
使用简单,开发人员可将 CustomElement 视为普通 HTMLElement 如 div、p 和 span 来使用,无需操心组件的创建和销毁。
开发难度低。仅需要具备 ES6 Class 使用经验便可以完成开发。
兼容性要求
CustomElement 定义时需提供 ES6 Class 类型参数,无法传递 ES5 的构造函数
需要引入额外的 Polyfill 解决问题
一旦定义无法撤回
使用 customElements.define 定义过的组件无法取消声明,即不存在 unRegistry 操作
无法使用不同的 ES6 Class 定义同名 CustomElement,仅首次定义生效
多团队协作时有概率产生 CustomElement 命名冲突,需妥善处理
给 CustomElement 传递参数较为困难
通常只能给 CustomElement 传递字符串类型 props
若要传递引用类型则需要显式地获取元素并将其视为普通对象,方可进行赋值(代码演示)
class CustomButton extends HTMLElement { xxx };
// 定义 custom-button 元素
window.customElements.define('custom-button', CustomButtom);
const customButton = document.body.querySelector('custom-button');
// 传递引用类型 props
customButton.message = { name: 'xxx' };
customButton.setParams({ age: 23 });
// Home.tsx
// 以下示例无法在 custom-button 上注册一个类型为 popout 的 CustomEvent
const Home: FC = (props) => {
const onPopout = () => {};
return <custom-button onPopout={onPopout}></custom-button>
};
// 需进行如下改造
const Home: FC = (props) => {
const onPopout = () => {};
const ref = useRef<HTMLElement | null>(null);
useEffect(() => {
if (!ref.current);
ref.current.addEventListener('popout', onPopout);
return () => {
ref.current.removeEventListener('popout', onPopout);
};
}, [ref]);
return <custom-button ref></custom-button>
};
Shadow DOM 可以将一个 “隐藏” 的、独立的 DOM 元素附着至其他元素下,ShadowDOM 内部的样式、行为都不会影响至外部。同样地,外部的样式、行为对 ShadowDOM 内部的影响 “有限”。
Shadow DOM 的子元素不会被外部环境样式所选中,起到了一定程度的样式隔离作用
Shadow DOM 内的样式也不会泄露至外部,无法影响宿主环境中的样式,内外相互隔离
Shadow DOM 仅是一个具有样式隔离作用的 “DocumentFragment”,自身不会对子元素造成样式上的影响
Shadow DOM 天生的样式隔离能力,使得它较为适合用于充当第三方前端组件的保护伞,尤其适合 EE Next SDK 的应用场景。
尽管 Shadow DOM 能够阻止外部样式表选中其中的子元素,但不能避免 CSS 属性继承,如图所示:
https://codepen.io/weidongxin/pen/NWgpJPJ
Light DOM 这一术语通常出现于存在 Shadow DOM 的场景中,主要指代 Shadow DOM 宿主元素下的所有子孙节点,用于同 Shadow DOM 作区分。
类似于 Vue.js 中的插槽概念,能够将 Shadow DOM 宿主元素下的子孙节点(即 Light DOM)引用至 Shadow DOM 内,将被引用的 DOM 元素 “复刻” 一份并渲染。
若宿主元素下同时存在 Light DOM 和 Shadow DOM,通常情况下会观察到在页面上没有正确渲染出 Light DOM 。
https://codepen.io/weidongxin/pen/ExvyzVd
Shadow DOM 与 Light DOM 不能共存,若两者同时存在则通常情况下 Light DOM 不会被渲染。
在 Shadow DOM 内使用 Slot 元素对 Light DOM 进行引用
仅有正确被引用的 Light DOM 部分才能被 “复制” 进入 Shadow DOM 中进行渲染
被引用的 Light DOM 部分样式依然受外部样式控制,因此能完全复刻 DOM 应有的样式
尽管 Shadow DOM 是属于 Web Component 标准中的一部分,但它并未被限制只能在 CustomElement 下使用,即便是普通 HTMLElement 也能够使用这一技术来实现样式保护。
Shadow DOM 只是一个具有样式隔绝功能的外衣,大多数情况下都不会造成宿主元素、 Shadow DOM 以及被引用的 Light DOM 的样式错误。一旦出现了明显的样式问题,需要以常规 CSS 样式处理的思路解决问题。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/F5P0hySgkjQ2LEowwQfSsw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。