Network Information API
一、为什么需要 Network Information API
1.1 自适应内容的必要性
用户的网络条件差异巨大:有人在 5G 下快速冲浪,有人在 2G 下艰难加载。同样一张图片、一个视频,在不同网络下应该有不同的质量。
Network Information API 允许 Web 应用了解用户的网络环境,从而做出合适的决策。
1.2 API 概述
if ('connection' in navigator) {
const connection = navigator.connection;
console.log('网络类型:', connection.effectiveType);
console.log('估算带宽:', connection.downlink, 'Mbps');
console.log('节省数据模式:', connection.saveData);
}
二、Navigator Connection API
2.1 基本属性
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
// 网络类型
connection.effectiveType; // 'slow-2g' | '2g' | '3g' | '4g'
// 估算带宽(Mbps)
connection.downlink;
// 往返延迟(ms)
connection.rtt;
// 是否启用节省数据模式
connection.saveData;
// 是否在线
navigator.onLine;
// CPU 核心数
navigator.hardwareConcurrency;
// 设备内存(GB)
navigator.deviceMemory;
2.2 监听网络变化
connection.addEventListener('change', () => {
console.log('网络变化:', connection.effectiveType);
console.log('带宽变化:', connection.downlink);
// 根据新网络条件调整内容
adjustContentQuality();
});
三、effectiveType 和 saveData
3.1 effectiveType
effectiveType 表示当前网络的有效类型:
// 'slow-2g' - 非常慢的网络,如 2G
// '2g' - 慢 2G 网络
// '3g' - 3G 网络
// '4g' - 4G 或更快的网络
function getContentStrategy() {
const type = navigator.connection?.effectiveType;
switch (type) {
case 'slow-2g':
case '2g':
return {
imageQuality: 'low',
preloadVideo: false,
autoplayVideo: false,
imageFormat: 'progressive-jpeg'
};
case '3g':
return {
imageQuality: 'medium',
preloadVideo: false,
autoplayVideo: false,
imageFormat: 'webp'
};
case '4g':
return {
imageQuality: 'high',
preloadVideo: true,
autoplayVideo: true,
imageFormat: 'avif'
};
default:
return {
imageQuality: 'medium',
preloadVideo: true,
autoplayVideo: false,
imageFormat: 'webp'
};
}
}
3.2 saveData
saveData 表示用户启用了节省数据模式:
function shouldLoadHighQuality() {
// 用户明确要求节省数据
if (navigator.connection?.saveData) {
return false;
}
// 或者网络很慢
const type = navigator.connection?.effectiveType;
if (type === 'slow-2g' || type === '2g') {
return false;
}
return true;
}
四、自适应内容策略
4.1 图片质量自适应
class AdaptiveImageLoader {
constructor() {
this.connection = navigator.connection;
this.quality = this.determineQuality();
}
determineQuality() {
if (this.connection?.saveData) return 'low';
if (this.connection?.effectiveType === '4g') return 'high';
if (this.connection?.effectiveType === '3g') return 'medium';
return 'low';
}
getImageUrl(baseUrl) {
const quality = this.quality;
if (quality === 'low') {
return baseUrl.replace('/upload/', '/upload/w_300,f_auto,q_auto:low/');
} else if (quality === 'medium') {
return baseUrl.replace('/upload/', '/upload/w_800,f_auto,q_auto:medium/');
} else {
return baseUrl.replace('/upload/', '/upload/w_1200,f_auto,q_auto:best/');
}
}
loadImage(imgElement, url) {
imgElement.src = this.getImageUrl(url);
}
}
4.2 视频码率自适应
class AdaptiveVideoPlayer {
constructor(videoElement) {
this.video = videoElement;
this.connection = navigator.connection;
}
selectQuality() {
const type = this.connection?.effectiveType;
const downlink = this.connection?.downlink || 5;
if (type === 'slow-2g' || type === '2g') {
return { url: this.lowQualityUrl, bitrate: 256 };
} else if (type === '3g' || downlink < 5) {
return { url: this.mediumQualityUrl, bitrate: 512 };
} else {
return { url: this.highQualityUrl, bitrate: 2048 };
}
}
loadVideo() {
const { url } = this.selectQuality();
this.video.src = url;
}
}
4.3 预加载策略
class SmartPreloader {
constructor() {
this.connection = navigator.connection;
}
shouldPreload(resourceType) {
// 节省数据模式,不预加载
if (this.connection?.saveData) {
return false;
}
const type = this.connection?.effectiveType;
// 预加载决策
if (type === '4g') {
return true; // 预加载所有
} else if (type === '3g') {
return resourceType !== 'video'; // 不预加载视频
} else {
return resourceType === 'critical'; // 只预加载关键资源
}
}
}
五、其他 Navigator API
5.1 navigator.onLine
window.addEventListener('online', () => {
console.log('网络已连接');
syncData();
});
window.addEventListener('offline', () => {
console.log('网络已断开');
enableOfflineMode();
});
5.2 navigator.hardwareConcurrency
// 获取 CPU 核心数
const cores = navigator.hardwareConcurrency;
console.log(`CPU 核心数: ${cores}`);
// 根据核心数决定并行度
const workers = Math.min(cores, 4);
5.3 navigator.deviceMemory
// 获取设备内存(GB)
const memory = navigator.deviceMemory;
console.log(`设备内存: ${memory}GB`);
// 根据内存决定缓存策略
if (memory < 4) {
// 低内存设备使用更小的缓存
cacheSize = 50 * 1024 * 1024; // 50MB
} else {
cacheSize = 200 * 1024 * 1024; // 200MB
}
六、注意事项
6.1 API 支持情况
Network Information API 不是所有浏览器都支持:
if ('connection' in navigator) {
// 支持
} else {
// 不支持,使用默认值
}
6.2 隐私考虑
这些 API 可能被用于指纹识别。浏览器可能会限制返回值的精度:
// 带宽可能不是精确值,而是估算值
const downlink = navigator.connection?.downlink; // 可能是 5 而不是精确值