Obs.js:面向所有人的上下文感知 Web 性能

本篇依然来自于我们的 《前端周刊》 项目!

由团队成员 田八 翻译,欢迎大家 进群 持续追踪全球最新前端资讯!!

原文地址:csswizardry

Obs.js 通过读取少量的浏览器信号(NavigatorBattery API),推断出用户的连接强度、电池状态以及设备性能。它将这些信号以 CSS 类的形式添加到 <html> 元素上,并且以属性的形式暴露在 window.obs 对象中,这样您就可以据此灵活地调整资源交付策略,比如:提供低分辨率的媒体内容、不使用网络字体、禁用自动播放的视频等等,您可以根据需要自由定制。

事实上,如果您的设备电量极低、已开启省电模式,或者网络连接较弱,那么您在上方 <h1> 标题中看到的将不会是那个圆润美观的 Fredoka 字体------而只会显示您系统默认的 system-ui 字体。

javascript 复制代码
(() => {

  // 只有在能够展示富媒体内容时,才加载 Google Fonts。
  // 在不支持相关 API 的浏览器中,我们则会直接加载字体文件。
  //
  // 此外,我们将字体脚本挂载到 body元素的末尾,而不是 head,
  // 这样就不会意外阻塞页面渲染。

  if (window.obs?.shouldAvoidRichMedia === true) {
    return;
  } else {
    const gf = document.createElement('link');
    gf.rel = 'stylesheet';
    gf.href = 'https://fonts.googleapis.com/css2?family=Fredoka:wght@300..700&display=swap';
    document.body.appendChild(gf);
  }

  // 有趣的是:由于这个 <script>标签是一个典型的、内联的、同步执行的脚本,
  // 所以在这个代码片段中提到的"body元素的末尾",实际上就是您此刻正在阅读的这段文字的紧后面。
  // 打开浏览器的开发者工具(DevTools),
  // 您会发现 Google Fonts 的样式表并不是位于 </body>标签之前,而是紧接在这个代码块之后。
  //
  // 还有一个有趣的地方:您此刻正在阅读的这段文字,其实就是浏览器刚刚执行过的 确切代码内容。
  // 只不过我们给它加上了 display: block;样式,让它以块级元素的形式显示出来而已。是不是很巧妙!
})();

Obs.jsHarry Roberts 开发并维护,遵循 MIT 许可证。

本页面展示了 Obs.js<html> 元素添加的 .has-* 类,以及它用于存储设备和网络信息的当前 window.obs 对象。

您可以尝试切换 省电模式(Data Saver)、插拔电源 或 切换网络(在支持的设备上),观察这些类和对象的实时更新。

html.classList

  • .has-bandwidth-high
  • .has-battery-charging
  • .has-connection-capability-moderate
  • .has-conservation-preference-neutral
  • .has-cpu-high
  • .has-delivery-mode-cautious
  • .has-device-capability-strong
  • .has-latency-medium
  • .has-ram-high

window.obs

json 复制代码
{
  "config": {
    "observeChanges": true
  },
  "dataSaver": false,
  "rttBucket": 150,
  "rttCategory": "medium",
  "downlinkBucket": 10,
  "downlinkCategory": "high",
  "connectionCapability": "moderate",
  "conservationPreference": "neutral",
  "deliveryMode": "cautious",
  "canShowRichMedia": true,
  "shouldAvoidRichMedia": false,
  "ramBucket": 8,
  "ramCategory": "high",
  "cpuBucket": 16,
  "cpuCategory": "high",
  "deviceCapability": "strong",
  "batteryCritical": false,
  "batteryLow": false,
  "batteryCharging": true
}

请注意:各浏览器对这些 API 的支持情况有所不同,其中 Chromium 内核浏览器提供的支持最为全面。

Demo

如果您的当前网络连接允许,您应该可以看到下方的小视频;如果条件不允许,则会显示一张静态的 <img> ------ 您看到的是什么?

ini 复制代码
(() => {

  // 如果网络连接状况良好,就嵌入视频;否则,只嵌入屏幕截图图片。

  const videoWrapper = document.getElementById('jsVideo');

  if (window.obs?.shouldAvoidRichMedia === true) {

    const img = new Image();
    img.src = './assets/poster.png';
    img.alt = '';
    img.width = '1500';
    img.height = '966';
    img.classList.add('c-hero');
    videoWrapper.appendChild(img);

  } else {

    const video = document.createElement('video');
    video.src = './assets/video.min.mp4';
    video.poster = './assets/poster.png';
    video.autoplay = true;
    video.loop = true;
    video.muted = true;
    video.controls = true;
    video.preload = 'auto';

    if (window.obs?.deliveryMode === 'cautious') {
      video.preload = 'metadata';
    }

    if (window.obs?.batteryLow === true) {
      video.autoplay = false;
    }

    videoWrapper.appendChild(video);

  }

})();

分析

如果您使用的 RUM(真实用户监控) 或 分析服务提供商 能够接收类似 window.obs 格式的数据,那您就可以将这些信息发送给他们! 您 并不一定非要用 Obs.js 来调整或改变您的网站------您完全可以将它作为一个 纯粹的观测工具,借此更深入地了解您的用户群体。

我会把所有数据都发送给我在 SpeedCurve 的朋友们。有了这些数据,我就能开始对 RUM(真实用户监控)数据进行细分,并制定针对不同用户群体的服务策略。

以下是我用来将 Obs.js 数据发送至 SpeedCurve 的具体代码片段:

javascript 复制代码
/**
 * 此前由 Obs.js 捕获的所有数据,现在都会发送至 SpeedCurve 了!
 *
 * I ❤️ SpeedCurve!
 */

(() => {
    // 如果 SpeedCurve 不可用,则直接退出
    if (!window.LUX || typeof window.LUX.addData !== 'function') return;

    const obs = window.obs || Object.create(null);

    // 我们计划发送的键值。请与 Obs.js 保持同步。
    const keys = [
        'canShowRichMedia',
        'connectionCapability',
        'conservationPreference',
        'cpuBucket',
        'cpuCategory',
        'dataSaver',
        'deliveryMode',
        'deviceCapability',
        'downlinkBucket',
        'downlinkCategory',
        'ramBucket',
        'ramCategory',
        'rttBucket',
        'rttCategory',
        'shouldAvoidRichMedia'
    ];

    for (const key of keys) {
        if (Object.prototype.hasOwnProperty.call(obs, key)) {
            window.LUX.addData(key, obs[key]);
        }
    }
})();

展示

这些优秀的人正在使用Obs.js

站点:

  • csswizardry.com 用法:
  • 在受限网络上提供低分辨率的英雄图像;
  • 在低电量模式下禁用过渡和动画。

提交您的网站

相关推荐
JarvanMo11 分钟前
2025 年真正有效的 App Store 优化(ASO)
前端·ios
{⌐■_■}13 分钟前
【JavaScript】前端两种路由模式,Hash路由,History 路由
前端·javascript·哈希算法
前端老鹰15 分钟前
HTML `<datalist>`:原生下拉搜索框,无需 JS 也能实现联想功能
前端·html
玲小珑17 分钟前
LangChain.js 完全开发手册(五)Runnable 接口与任务编排系统
前端·langchain·ai编程
江城开朗的豌豆35 分钟前
解密useEffect依赖数组
前端·javascript·react.js
江城开朗的豌豆43 分钟前
React Hooks必杀技:前端工程师小杨带你玩转常用API!
前端·javascript·react.js
江城开朗的豌豆1 小时前
Redux状态更新:异步还是同步?
前端·javascript·react.js
前端小巷子1 小时前
Vue 项目性能优化实战
前端·vue.js·面试
Aphasia3111 小时前
useEffect 中Clean up 函数的执行机制
前端·react.js·面试
xw51 小时前
我的后台管理项目报Error: spawn …esbuild.exe ENOENT了
前端