总所周知,写文章需要一个标题。虽然我们搞代码的人一般都喜欢单刀直入,但是受制于文体的约束和发表载体的要求,有时不得不想一个标题。而起一个标题,不亚于起一个函数名或者变量名。单就这篇文章,我就有好几个草稿标题,例如:《页面加载指标演进之路》,《Element Timing:一种全新的页面速度指标》,《如何最准确地测量网页加载速度》,《新前端下的页面加载速度》,甚至《Element Timing In Action》,《三分钟学会测量页面速度》。最后综合考虑了读者的承受能力,编辑的意见,以及最最重要的:本人的孱弱写作实力,就取了个这样的一个非常大众化,既不会一眼就被当成垃圾,也不会被人挑出来仔细找茬的标题。
好了,废话不能多说,直接进入正题。
上古时期(指距今 10+ 年前的 jquery 纪元),我们开发网页还停留在编写静态页面结构,用 JS 脚本对 DOM 进行直接操作,添加删除一些额外页面元素上。此时,DOMReady 基本就可以满足计算页面加载完成时间的需求,DOMReady (在 DOM 事件中是 DOMContentLoaded)代表页面文档完全加载并解析完毕, 一般包含html文档分析以及DOM树的创建、外链脚本的加载、外链脚本的执行以及内联脚本的执行,而不会等待样式文件,图片文件,子框架页面的加载。一般在页面 header 中打个时间戳,再在 jQuery 的 domReady 事件中打个时间戳,我们就可以计算到大致的 DOMReady 耗时了。
中古时期(指距今 10-5 年左右的 Ajax 纪元),网页的交互形式更加丰富多样,Gmail 为首的富网页应用在用户体验大幅增强的同时,也给细粒度的网页加载时间记录带来了需求。因此,从2010年开始Web 性能工作组就已经为 Web 引入了大量时间信息记录,可以通过 window 对象的 performance 属性去获取。这就是后来我们所熟知的 Navigation Timing。
Navigation Timing 接口所提供的数据大致如图:
基本上囊括了从网页开始网络请求到页面完整加载并执行完资源并完成初始化 DOM 节点的时间。我们直接使用 performance.timing,就可以轻松获得这些时间来帮助分析页面的加载时间。
近古时期(指距今 5-2 年左右的 react 纪元),由于各种前端框架(React,vue 等)雨后春笋似的涌出,加上 webpack 这种前端构建神器的出现,导致 Web 页面的开发难度迅速下降,复杂度也直线上升。重前端的应用大行其道,页面加载脚本的时间也迅速变长,很多网站为了体验采取了渐进式加载的策略,以解决等待脚本执行时白屏时间过长的问题。因此,渐进式网页渲染指标也应运而生。
渐进式网页指标一般有这几个:
其中 FMP 因为依赖算法猜测有效元素,所以目前已经基本被弃用。这几个指标的可视化意义可以参考以下两张图:
由于复杂页面的元素往往很多,FCP 所观测的元素可能只是 无足轻重 的一个 Loading 标记或者一个边栏,因此对于真实的用户来说,并不能代表页面的“首屏时间”。反而,在某些逻辑复杂的页面中,由于 JS 代码的执行时间长,或者依赖很多后端接口来渲染页面,经常会导致页面最重要的数据展示的时间远远长于页面 OnLoadEvent 触发的时间,此时,对于用户来说最直观感觉的到的“首屏时间”,往往就是 LCP 的时间。
这就是现在很多前端页面性能工具都会把 LCP 列入一个重要的参考指标的原因。
现代时期(指距今 1-0 年左右的微前端纪元),LCP 的计算逻辑是浏览器给定的,在不同页面中,浏览器所认为的 最大的可见元素 也未必是我们业务中 真正重要的 内容。并且在微前端流行的现代,不仅仅是同一应用的不同页面采用单页模式,甚至不同子应用的加载也可能通过 hash 路由来驱动。对于这种单页应用来说,以上的各个指标其实都无法满足在主体框架加载完成后切换不同页面时的重新计算。那么我们是不是只能够完全依赖业务开发本身去在代码里主动打点和上报加载时间呢?那也未必。
让我们来看看 W3C 的一个新草案,元素计时 api :https://wicg.github.io/element-timing/ 。尽管这个 API 还处于草案阶段,但是 Chrome 和 Edge 两个浏览器其实早已在新版本给予了支持:兼容性
Element Timing API 的目的是让 Web 开发人员或分析工具能够测量页面上关键元素的渲染时间,比起 LCP ,我们能够自己来定义关键元素,这正是Element Timing 的最大魅力。
Element Timing 支持的元素有:
举个例子:
<img src="image.jpg" elementtiming="big-image">
<p elementtiming="text" id="text-id">text here</p>
const observer = new PerformanceObserver((list) => {
let entries = list.getEntries().forEach(function (entry) {
console.log(entry);
});
});
observer.observe({ entryTypes: ["element"] });
// 输出 entry 内容:
// {
// duration: 0
// element: p.aimake-site-name
// entryType: "element"
// id: ""
// identifier: "text-id"
// intersectionRect: DOMRectReadOnly {x: 236, y: 130, width: 144, height: 28, top: 130, …}
// loadTime: 0
// name: "text-paint"
// naturalHeight: 0
// naturalWidth: 0
// renderTime: 10850.899999976158
// startTime: 10850.899999976158
// url: ""
// }
但是需要注意的是,并不是所有文本节点都可以通过添加 elementtiming="" 让 Element Timing API 识别,WICG 的解释中有一段注意事项:
We say that a text node belongs to the closest block-level Element ancestor of the node. This means that an element could have 0 or many associated text nodes with it.
We say that an element is text-painted if at least one text node belongs to and has been painted at least once. Thus, the text rendering timestamp of an element is the time when it becomes _text-painted_.
Let the text rect of a text node be the display rectangle of that node within the viewport. We define the text rect of an element as the smallest rectangle which contains the geometric union of the text rects of all text nodes which belong to the element.
读起来比较难懂,但是实际上它想说明的是,只有满足以下条件的文本节点才能够被记录:
举一些例子就懂了:
<html>
<p elementtiming = "p1"><p>1</p></p> <!-- 无效 -->
<p elementtiming = "p2">2</p> <!-- 有效 -->
<span elementtiming = "span1">span1</span> <!-- 无效 -->
<div elementtiming = "div1"><image elementtiming = "img1" src="https://img.alicdn.com/tfs/xxx.png"></image></div> <!-- div1 无效,其中的 img1 有效 -->
<div elementtiming = "div2"><span>1</span></div> <!-- 有效 -->
<div elementtiming = "div3"><p>2</p></div> <!-- 无效 -->
<div elementtiming = "div4"><h1>3</h1></div> <!-- 无效 -->
<div elementtiming = "div5"><b>4</b></div> <!-- 有效 -->
<b elementtiming = "b1">b1</b> <!-- 无效 -->
<i elementtiming = "i1">i1</i> <!-- 无效 -->
<h1 elementtiming = "h1">h1</h1> <!-- 有效 -->
<section elementtiming = "section1">section1</section> <!-- 有效 -->
</html>
在添加了自定义 elementtiming 属性后,当所标记的图像或者文本节点被 真正渲染 时,浏览器就会记录下时间。因此,我们可以在不同应用中让开发同学直接给能够标志 首屏 的元素添加该属性,即可由采集脚本通过监听 PerformanceObserver 来统一采集到元素绘制的时间点(renderTime)了。
通过使用 Element Timing API ,我们能够更精确记录到每个应用,页面,甚至功能模块的加载时长。这才是最现代,最前沿的页面加载时间方案,其余方案最终都将被埋葬在历史的尘埃中! 开个玩笑
江山代有才人出,各领风骚数百年
一般来说,结尾并没有标题那么重要,因此我也不需要费脑子去想 N 个结尾了,直接简单总结一下:无论前端发展到什么程度,Timing 的标准总会追上你!
希望如果有读者大神如果受到了一点点启发,能够给写个包含 Element Timing 指标的性能库造福我们。毕竟我就是懒,以上都是我自己 YY 的用法。在此先提前感谢了。
链接:https://segmentfault.com/a/1190000041345779
作者:ES2049 | 佚名
同时针对大段的文本,不能整段的去读,要按照标点符号进行断句处理。重点当然就是先获取到当前标签上的文本,再把文本转化成语音即可。
CSS以图换字的技术,很久都没人提起了。它是一种在h1标签内,使用图像替换文本元素的技术,使页面在设计和可访问性之间达到平衡。本文将详细介绍CSS以图换字的9种方法
在网页开发中,经常会遇到把一些通用内容的页面集中到一个页面中,需要使用这些页面只需要包含引入即可,这样有利于维护和修改,当通用页面修改时只需更改一个文件就可以了,不需要每个文件单独处理。
开发网站之前,你需要知道哪些事情呢?每个开发者的答案可能都不太相同,这里整理为6个方面:界面和用户体验、安全性、性能(Performance)、搜索引擎优化、技术(Technology)、解决bug
理解大型分布式网站你必须知道这些概念:1. I/O优化、2. Web前端调优、3.服务降级(自动优雅降级)、4.幂等性设计、5.失效转移、6.性能优化、7. 代码优化、8. 负载均衡、9.缓存等
每一个网页或者说是web页都有其固定的后缀名,不同的后缀名对应着不同的文件格式和不同的规则、协议、用法,最常见的web页的后缀名是.html和.htm,但这只是web页最基本的两种文件格式,今天我们来介绍一下web页的其它一些文件格式。
网页自动跳转,是指当用户访问某个网页时,被自动跳转到另一个网页中去。网页自动跳转的主要作用是,当域名变更后,或者网站里的一个或多个网页被删除后,可以使用这种方式将用户引导到其它正常的网页中去,从而留住用户。
锚链链接是一个非常重要的概念,在网页中增加恰当的锚链接,会让所在网页和所指向网页的重要程度有所提升,从而影响到关键词排名。锚链接对SEO的作用主要体现在以下几个方面
HTML几乎是平铺直叙的。CSS是一个伟大的进步,它清晰地区分了页面的结构和外观。在本教程中,您将了解在浏览器中看到的内容是如何实际呈现的,以及如何在必要时进行抓取。
VMware Workstation提供了两种虚拟机上网方式,一种bridge,一种NAT,bridge可以获得公网地址,而NAT只能是内网地址了。例1:在虚拟机内搭建http服务器,使用公网地址访问,例2: ssh端口映射
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!