Obs.js 通过读取少量的浏览器信号(Navigator 和 Battery API),推断出用户的连接强度、电池状态以及设备性能。它将这些信号以 CSS
类的形式添加到 <html>
元素上,并且以属性的形式暴露在 window.obs
对象中,这样您就可以据此灵活地调整资源交付策略,比如:提供低分辨率的媒体内容、不使用网络字体、禁用自动播放的视频等等,您可以根据需要自由定制。
事实上,如果您的设备电量极低、已开启省电模式,或者网络连接较弱,那么您在上方 <h1>
标题中看到的将不会是那个圆润美观的 Fredoka
字体——而只会显示您系统默认的 system-ui
字体。
(() => {
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);
}
})();
Obs.js 由 Harry 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
{
"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>
—— 您看到的是什么?

(() => {
// 如果网络连接状况良好,就嵌入视频;否则,只嵌入屏幕截图图片。
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
的具体代码片段:
(() => {
if (!window.LUX || typeof window.LUX.addData !== 'function') return;
const obs = window.obs || Object.create(null);
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:

转自https://juejin.cn/post/7545317605810651136
该文章在 2025/9/8 9:03:53 编辑过