

customElements 实战之 Lite-embed | 全栈修仙之路
source link: http://www.semlinker.com/lite-embed/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

customElements 实战之 Lite-embed
创建了一个 “重学TypeScript” 的微信群,想加群的小伙伴,加我微信 “semlinker”,备注 “1” 。阿里、京东、腾讯的大佬都在群里等你哟。
一、Lite-embed 简介
Lite-embed 的灵感来源于 paulirish 大神的 lite-youtube-embed 项目:
Provide videos with a supercharged focus on visual performance. This custom element renders just like the real thing but approximately 224X faster.
提供具有视觉效果的视频。这个自定义元素的渲染方式与真实的效果一样,但是速度提高了约 224 倍。
Lite-embed 是基于 customElements Web Components 规范开发的组件,支持以 iframe 方式快速地嵌入第三方站点,如 Bilibili、Youku、QQ、Youtube、Vimeo 和 Codepen 等。
通过扩展 Lite-embed 项目中 services.ts 服务类的匹配规则,开发者可以方便地内嵌其它支持 iframe 方式嵌入的站点,除此之外基于 services.ts 服务类,也可以让富文本编辑器支持自动解析剪贴板中的网址,自动以 iframe 的方式嵌入所指定的内容。这里我们以 B 站的某个视频为例,它的原始地址是:
1 | https://www.bilibili.com/video/av53834726?spm_id_from=333.851.b_62696c695f7265706f72745f616 |
其对应的 iframe 内嵌代码如下:
1 | <iframe src="//player.bilibili.com/player.html?aid=53834726&cid=94168196&page=1" |
当用户需要嵌入上述网址对应的视频时,一般需要手动点击视频下方的分享链接,然后复制上述的 iframe 内嵌代码,再添加到目标页面中。Lite-embed 所实现的功能之一就是实现自动解析,即根据设置的地址,按照一定的匹配规则,最终生成对应的 iframe 内嵌代码。对于上述的需求,Lite-embed 使用起来也很简单,具体如下:
1 | <!-- Bilibili --> |
当然如果只是实现上述功能的话,那么 Lite-embed 并没有多大的意义。Lite-embed 除了实现自动解析功能之外,还实现了在悬停视频封面或海报时,预热(可能)要使用的 TCP 连接和 iframe 内嵌网页懒加载的功能。
二、Lite-embed 开发实战
2.1 实现自动解析
前面我们已经简单介绍了 Lite-embed 的功能,下面我们来介绍一下如何一步步实现 Lite-embed 组件。首先我们先来定义 LiteEmbed 类,该类继承于 HTMLElement 类,在 LiteEmbed 类中除了前面示例中使用的 src 和 height 属性之外,我们还定义了 posterUrl、prefetchUrlSet 和 embedOption 属性。
1 | class LiteEmbed extends HTMLElement { |
embedOption 属性的类型是 EmbedOption,它用于表示内嵌站点的配置信息,EmbedOption 接口定义:
1 | export interface EmbedOption { |
接着我们来介绍如何实现自动解析,要实现自动解析的前提是原始 url 地址和 iframe 内嵌地址这两个地址之间存在一定的映射规则。以 B 站为例,它们之间的映射规则如下:
通过观察上图可知原始 url 地址上的 av 字符串之后的序列号对应 iframe src 地址中 aId 参数的值。所以我们可以利用正则表达式来实现地址的映射,具体如下:
1 | bilibili: { |
上面除了定义了地址映射相关的 regex、embedUrl 和 html 三个属性之外,我们还定义了 height 和 preconnects 属性,分别表示 iframe 的默认高度和预链接地址列表。除了 B 站之外,目前 Lite-embed 还支持 Youku、QQ、Youtube、Vimeo 和 Codepen 等站点,为了统一处理映射规则并方便后期扩展,我们来新增一个 Matcher 类,具体代码如下:
Matcher 类
1 | export default class Matcher { |
在 Matcher 类中我们定义了两个静态方法,即 matches 和 match 方法。在 matches 方法内部会获取预设的规则,然后逐一进行地址匹配。而 match 方法内部实现的主要功能是地址的映射和参数的填充。介绍完自动解析的实现方式,接下来我们来介绍如何预热 TCP 链接。
2.2 预热 TCP 链接
在介绍如何预热 TCP 链接前,我们需要了解一些前置知识,如 HTML link 标签 rel 属性的一些特殊用途和自定义元素的生命周期钩子。
在实际开发中可以通过设置 link 标签 rel 属性来提升网页的渲染速度(有兼容性问题),常见的类型如下:
prefetch:提示浏览器提前加载链接的资源,因为它可能会被用户请求。建议浏览器提前获取链接的资源,因为它很可能会被用户请求。 从 Firefox 44 开始,考虑了
crossorigin
属性的值,从而可以进行匿名预取。preconnect:向浏览器提供提示,建议浏览器提前打开与链接网站的连接,而不会泄露任何私人信息或下载任何内容,以便在跟随链接时可以更快地获取链接内容。
preload:告诉浏览器下载资源,因为在当前导航期间稍后将需要该资源。
prerender:建议浏览器事先获取链接的资源,并建议将预取的内容显示在屏幕外,以便在需要时可以将其快速呈现给用户。
dns-prefetch:提示浏览器该资源需要在用户点击链接之前进行 DNS 查询和协议握手。
若需了解完整的链接类型,可以访问 MDN - Link Type。
为了支持动态添加 link 元素设置该元素对应的 rel 属性,我们来定义一个 addPrefetch 方法,该方法用于实现预加载或预链接,具体实现如下:
1 | static addPrefetch(kind: string, url: string, as?: string) { |
接着我们来介绍另一个知识点 —— 自定义元素的生命周期钩子。自定义元素可以定义特殊生命周期钩子,以便在其存续的特定时间内运行代码。 这称为自定义元素响应。目前自定义元素支持的生命周期钩子如下:
名称 | 调用时机 |
---|---|
constructor | 创建或升级元素的一个实例。用于初始化状态、设置事件侦听器或创建 Shadow DOM。参见规范,了解可在 constructor 中完成的操作的相关限制。 |
connectedCallback | 元素每次插入到 DOM 时都会调用。用于运行安装代码,例如获取资源或渲染。一般来说,您应将工作延迟至合适时机执行。 |
disconnectedCallback | 元素每次从 DOM 中移除时都会调用。用于运行清理代码(例如移除事件侦听器等)。 |
attributeChangedCallback(attrName, oldVal, newVal) | 属性添加、移除、更新或替换。解析器创建元素时,或者升级时,也会调用它来获取初始值。Note: 仅 observedAttributes 属性中列出的特性才会收到此回调。 |
adoptedCallback() | 自定义元素被移入新的 document (例如,有人调用了 document.adoptNode(el) )。 |
下面我们将使用 constructor 和 connectedCallback 钩子,在 constructor 钩子中完成 LiteEmbed 类相关属性的初始化,在 connectedCallback 钩子中完成播放按钮的创建和设置相关的事件监听,相关的处理逻辑比较简单,我们直接上代码:
构造函数
1 | class LiteEmbed extends HTMLElement { |
生命周期钩子
1 | connectedCallback() { |
在 connectedCallback 方法中,我们监听 pointerover
事件,在该事件触发后,我们调用 warmConnections 方法提前预热可能要使用的 TCP 链接,warmConnections 方法内部的逻辑也简单就是遍历预设的 preconnects 数组,然后动态创建 link 标签,相关的代码如下:
1 | static warmConnections(preconnects: string[]) { |
2.3 懒加载 iframe 内嵌网页
Lite-embed 组件要实现的最后一个功能就是懒加载 iframe 内嵌网页,即当用户点击海报或播放按钮的时候,才创建 iframe 元素进而开始加载内嵌网页。这里我们通过定义一个 addIframe 方法来实现该功能:
1 | addIframe() { |
至此 Lite-embed 的所有功能已经介绍完了,就差最后一步即定义 lite-embed 元素,代码很简单一行就搞定了:
1 | customElements.define('lite-embed', LiteEmbed) |
本文详细介绍了如何利用 customElements Web Components 规范来开发 Lite-embed 组件,该组件虽然带了一些好处,比如提高嵌入页面的加载速度,但同时也存在一些问题,比如在点击视频封面或海报时,才开始动态加载 iframe,会造成需要二次点击才能正常播放嵌入的视频。对 Lite-embed 组件感兴趣的小伙伴可以访问 lite-embed,具体的项目地址如下:
四、参考资源
欢迎小伙伴们订阅全栈修仙之路,及时阅读 TypeScript、Node/Deno、Angular 技术栈最新文章。

Recommend
-
66
(这是一个系列文章:预计会有三期,第一期会以同构构建前后端应用为主,第二期会以GraphQL和MySQL为主,第三期会以Docker配合线上部署报警为主) 作者: 赵玮龙 (为什么总是我,因为有队友们无限的支持!!!) 首先声明下写这篇文章的初衷,自己也还是在
-
41
“We’re finally finished removing jQuery from https://t.co/r2QL2aHBfa frontend. What did we replace it with? No framework whatsoever: • querySelectorAll, • fetch for ajax, • delegated-events for event handling, • polyfills for standard...
-
64
菜菜的涨工资申请还在待审批中.... 作为一个技术人员,技术的问题还是要解决。经过线上日志的分析,日志采用小时机制...
-
39
前言 在若干次前的一场面试,面试官看我做过python爬虫/后端 的工作,顺带问了我些后端相关的问题:你觉得什么是后端? 送命题。当时脑瓦特了,答曰:逻辑处理和数据增删改查。。。 当场被怼得体无完肤,羞愧难当。事后再反思这问题,结合资料总结了一下。发现自己...
-
41
前言 好久没写博客了,我原先的标题是 “从输入url到页面加载完成的XXX”? 但想着,这是别人嚼烂很多次的内容,缺乏挑战性,而且,页面操作过程中能优化的地方实在太多了。 那就干脆给自己挖个坑吧,好歹也在运维开发部待过一年的时间。 本文将尝试从前后端或运维多...
-
42
程序员修仙之路--优雅快速的统计千万级别uv(留言送书) ...
-
68
Lite-embed 的灵感来源于 paulirish 大神的 lite-youtube-embed 项目: Provide videos with a supercharged focus on visual performance. This cus...
-
7
npm是什么? 想了解npm是什么,给先了解它是为谁服务的,为什么需要它?npm是为NodeJS服务的,是随同NodeJS一起安装的包管理工具。也就是说安装了NodeJS就默认安装了npm。是不是很密切?没有错,NodeJS是服务器脚本语言,和它类似的语言有java、asp.net、php...
-
5
复活“赛博朋克”:奈飞的“修仙”之路游戏进行时·2022-10-13 23:35《赛博朋克2077》大卖,动画游戏协同IP运营。上周有件稀罕...
-
3
G行探索全栈云容器环境降本增效之路——基础篇 作者:王雷硕 2023-12-05 07:31:26 本文首先介绍容器环境各层使用资源的背景,通过生产环境的资源使用实践,分析造成资源使用率低于预期的原因,最后提出相应解决方案...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK