Pace源码剖析(一):四大进度收集器如何感知页面加载——Ajax、Elements、Document与EventLag

发布时间:2026/9/19 17:32:37
Pace源码剖析(一):四大进度收集器如何感知页面加载——Ajax、Elements、Document与EventLag Pace源码剖析一四大进度收集器如何感知页面加载——Ajax、Elements、Document与EventLag【免费下载链接】paceAutomatically add a progress bar to your site.项目地址: https://gitcode.com/gh_mirrors/pa/pacePace 是一个能自动为网站添加进度条的开源 JavaScript 库它的核心思路是同时派出四大进度收集器Ajax、Elements、Document、EventLag从网络请求、DOM 元素、文档就绪状态、事件循环延迟四个维度感知页面加载进度再把结果平滑地渲染成顶部那条优雅的进度条。本文带你逐行走读 pace.js 源码看看这四个侦查兵分别在做什么。一、先看全景一个文件里的四大模块 整个库的逻辑全部集中在 pace.js 中压缩后仅 4KB 左右。它的运行流程可以概括为一条流水线收集器Sources→ 缩放器Scaler→ 进度条Bar四个收集器各自维护一个progress0~100数值Scaler按帧读取各收集器的进度做追赶 缓动平滑处理Bar负责创建 DOM 节点用translate3d移动进度条位置。四大收集器在初始化时被统一注册源码位置在 pace.js#L869-L894SOURCE_KEYS { ajax: AjaxMonitor, elements: ElementMonitor, document: DocumentMonitor, eventLag: EventLagMonitor };init()会遍历[ajax, elements, document, eventLag]只要配置中对应项不为false就实例化并加入sources数组。也就是说每个收集器都可以单独关闭这正是后文配置指南的基础。进度条本体由Bar类负责见 pace.js#L262-L342。它的render()方法把进度换算成translate3d(x%, 0, 0)的 GPU 加速位移同时把百分比写入data-progress-text属性——这就是很多主题 CSS 能显示37%文字的原因。二、Ajax 收集器监听页面上的每一次请求 Ajax 收集器AjaxMonitorpace.js#L581-L613的职责是监控页面上所有的异步请求每个进行中的请求都算未完成的工作。它由三个部分组成。2.1 劫持请求构造函数怎么偷听到请求关键在RequestIntercept类pace.js#L447-L514。它在库加载时保存了原始的window.XMLHttpRequest、window.XDomainRequest、window.WebSocket然后把它们替换成包装过的构造函数每次new XMLHttpRequest()时包装器创建真实请求对象并给它打补丁——重写req.open方法一旦业务代码调用open(method, url)包装器就触发request事件把请求信息交给AjaxMonitor.watch()。这是典型的猴子补丁Monkey Patching手法不改业务代码只改浏览器 API 本身。WebSocket 同样被包装受ajax.trackWebSockets选项控制所以实时推送类页面也能被感知到。哪些请求会被跟踪由shouldTrack()pace.js#L429-L445决定默认只跟踪GET请求和 socket另外提供了Pace.ignore()与Pace.track()pace.js#L411-L427两个函数用栈机制ignoreStack临时标记这段代码里的请求要忽略/强制跟踪避免预缓存请求触发进度条。2.2 单请求进度XHRRequestTracker每个被跟踪的请求都会生成一个XHRRequestTrackerpace.js#L615-L654它内部有个巧妙的两档策略场景进度计算方式浏览器支持ProgressEvent且能算出总大小lengthComputable100 × 已加载字节 / 总字节数精确计算拿不到总大小progress progress (100 - progress) / 2即永远向 100 逼近一半呈现越接近终点越慢的观感老浏览器只有readyStatereadyState 3时直接记为 50%请求的load、abort、timeout、error任一事件触发后进度置 100 并通知AjaxMonitor移除该 tracker。2.3 何时重新开始两条重启规则 Ajax 收集器还承担了进度条重启的触发职责pushState 重启库加载时重写history.pushState与replaceStatepace.js#L847-L867单页应用每次路由切换都会调用Pace.restart()进度条从头再来慢请求重启监听request事件后延迟restartOnRequestAfter默认 500ms检查请求是否仍在飞行中readyState介于 0 和 4 之间若是则重启进度条并接管该请求pace.js#L543-L579。此外ajax.ignoreURLspace.js#L525-L541支持字符串或正则黑名单埋点、统计类请求可以一键屏蔽。三、Elements 收集器盯着 DOM 等元素出现 ElementMonitorpace.js#L675-L701的思路非常朴素关键元素渲染出来了页面就算完成了。它为每个选择器创建一个ElementTrackerpace.js#L703-L730后者用递归setTimeout轮询if (document.querySelector(this.selector)) { return this.done(); // 出现了 → 完成 } setTimeout(() this.check(), options.elements.checkInterval); // 没出现 → 100ms 后再问一次轮询间隔由elements.checkInterval控制默认100ms默认选择器是[body]几乎总是立刻完成所以默认配置下它基本不拖后腿真正的用法是给选择器写**成功或错误态的逗号组合**例如.timeline, .timeline-error——两者任一出现即算完成避免出错时元素永远不出现导致进度条卡死详见 README.md 的 Elements 一节。四、Document 收集器读取文档就绪状态 DocumentMonitorpace.js#L732-L754是四个收集器中最短的一个只有 20 来行。它把document.readyState的三个状态直接映射成进度states { loading: 0, interactive: 50, complete: 100 };构造时先按当前状态取初始值已晚加载则直接 100随后接管document.onreadystatechange事件保留了用户原有的回调并链式调用。它代表的是文档骨架层面的进度脚本执行、DOM 解析完毕走到 50%资源全部加载完毕complete到达 100%。五、EventLag 收集器用卡顿反推进度 ⏱️这是四个收集器里最有意思的一个。EventLagMonitorpace.js#L756-L785基于一个朴素假设页面在加载时浏览器忙着解析 HTML、执行脚本事件循环会被拖延页面越空闲定时任务越准点。它每50ms设一个定时器每次触发时测量实际延迟 - 预期 50ms得到本次 lag保留最近sampleCount个样本默认 3求平均绝对值avg然后进度公式progress 100 × 3 / (avg 3)——平均延迟越小进度越接近 100完全空闲时恰好 100完成判定累计minSamples次采样默认 10 次且平均 lag 小于lagThreshold默认 3ms判定页面已空闲进度锁定 100 并clearInterval停止计时。也就是说EventLag 收集器本质上是在做CPU 空闲度采样它兜住了那些没有任何 XHR、也没有关键元素、但一直在跑脚本的场景。六、最后一步Scaler 把四个进度揉成丝滑动画 ✨四个收集器的原始值都带毛刺有的 0 直接跳 100直接上屏会很难看。Scaler类pace.js#L787-L831用requestAnimationFrame逐帧约 33ms 一帧兼容实现见 pace.js#L82-L98做两层加工catchup追赶真实值与显示值的差距除以catchupTime默认 100ms以固定速率追上去保证真完成后进度条不会立刻弹满rate变速按最近一次变化的斜率外推并用easeFactor默认 1.25做缓动衰减——进度越高爬得越慢形成头快尾慢的自然节奏。Pace.go()pace.js#L916-L956是总调度每帧对每个收集器的每个元素tick()一次取平均后交给全局uniScaler再更新Bar。当所有 Scaler 都done或进度满 100 时触发done事件并按minTime默认 250ms/ghostTime默认 100ms取最大值延迟淡出——这就是进度条跑满了还会多留一会儿的原因。七、速查表四大收集器对比与默认配置收集器感知对象完成信号关键默认值AjaxXHR / XDR / WebSocket 请求所有请求结束trackMethods: [GET]、restartOnRequestAfter: 500msElements指定选择器的 DOM 元素每个选择器都匹配到checkInterval: 100ms、selectors: [body]Documentdocument.readyStatecompleteloading0 / interactive50 / complete100EventLag事件循环延迟连续空闲采样达标采样间隔 50ms、minSamples: 10、lagThreshold: 3ms所有默认值集中定义在 pace.js#L14-L40 的defaultOptions。想关闭某个收集器只需在window.paceOptions或script标签的data-pace-options里将其设为falsepaceOptions { ajax: false, eventLag: false };八、小结一文读懂 Pace 的感知体系 回顾整条链路RequestIntercept劫持网络 API 喂给AjaxMonitorElementTracker定时轮询喂给ElementMonitorreadyState映射喂给DocumentMonitor定时器漂移反推喂给EventLagMonitor——四路信号汇入Scaler平滑、再由Bar渲染。这套多信号融合 时间平滑的架构就是 Pace 无需任何手动埋点就能自动感知页面加载的全部秘密。相关资源完整配置说明与主题列表README.md各主题样式themes/ 下 black / blue / green 等 10 套配色 × 15 种主题以及 pace-theme-default.css压缩版入口pace.min.js下一篇预告Pace 源码剖析二将深入Scaler的缓动数学、Pace.on/off/once事件系统与extraSources自定义收集器扩展。【免费下载链接】paceAutomatically add a progress bar to your site.项目地址: https://gitcode.com/gh_mirrors/pa/pace创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询