现代浏览器 API 与 Web 平台能力地图

系统性梳理现代浏览器原生 API 能力地图:Web Workers / Shared Workers 多线程计算、IndexedDB / Cache API / Storage API 客户端存储、Intersection Observer / Resize Observer / Mutation Observer 布局观测、Web Share / Web Share Target / Contact Picker 社交集成、Clipboard API / File System Access / Drag & Drop 数据交互、Web Bluetooth / Web NFC / Web Serial / Web HID / Web USB 硬件连接、Web Speech / Web Audio / MediaRecorder 多媒体、Payment Request / Credential Management 身份与支付、BroadcastChannel / Beacon / Reporting API 页面通信与报告。

现代浏览器已经是一个具备操作系统能力的平台。 从多线程计算到硬件连接,从本地文件系统到身份支付——掌握这些 API 能让 Web 应用跳出「页面」的局限,提供接近原生的体验。


一、多线程:Web Workers

1.1 Dedicated Worker(专用)

// worker.js
self.onmessage = (event) => {
  const { data, type } = event.data;

  if (type === 'heavy-computation') {
    const result = fibonacci(data);
    self.postMessage({ type: 'result', value: result });
  }
};

function fibonacci(n) {
  return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
// main.js
const worker = new Worker('/worker.js');

worker.postMessage({ type: 'heavy-computation', data: 40 });

worker.onmessage = (event) => {
  console.log('Result:', event.data.value); // 102334155
  worker.terminate();
};

// 用 Comlink 简化通信
import * as Comlink from 'comlink';
const api = Comlink.wrap(new Worker('/worker.js'));
const result = await api.heavyComputation(40);

1.2 Shared Worker(共享)

多个标签页共享同一个 Worker:

// shared-worker.js
const connections = [];

self.onconnect = (event) => {
  const port = event.ports[0];
  connections.push(port);

  port.onmessage = (e) => {
    // 广播给所有连接
    connections.forEach(conn => {
      if (conn !== port) conn.postMessage(e.data);
    });
  };

  port.start();
};

二、客户端存储

2.1 存储方案对比

API容量持久性结构化查询适用场景
localStorage~5-10MB持久简单键值(token、theme)
sessionStorage~5-10MB标签页临时状态(表单草稿)
IndexedDB硬盘 50%+持久Indexed大量结构化数据、离线应用
Cache API硬盘 50%+持久无(按 Request)Service Worker 缓存
Origin Private File System用户授权持久本地文件读写

2.2 IndexedDB 封装

// idb.ts(基于 idb 库封装)
import { openDB, DBSchema } from 'idb';

interface MyDB extends DBSchema {
  documents: {
    key: string;
    value: {
      id: string;
      title: string;
      content: string;
      updatedAt: number;
    };
    indexes: { 'by-date': number };
  };
}

const db = await openDB<MyDB>('my-app', 1, {
  upgrade(db) {
    const store = db.createObjectStore('documents', { keyPath: 'id' });
    store.createIndex('by-date', 'updatedAt');
  }
});

// 写入
await db.put('documents', { id: 'doc-1', title: 'Hello', content: '...', updatedAt: Date.now() });

// 读取
const doc = await db.get('documents', 'doc-1');

// 查询索引
const recent = await db.getAllFromIndex('documents', 'by-date', IDBKeyRange.lowerBound(Date.now() - 86400000));

2.3 Storage API:持久化与配额

// 请求持久化存储(不会被浏览器自动清除)
if (navigator.storage && navigator.storage.persist) {
  const isPersistent = await navigator.storage.persist();
  console.log('Persistent storage:', isPersistent);
}

// 查看配额
const estimate = await navigator.storage.estimate();
console.log('Usage:', estimate.usage);
console.log('Quota:', estimate.quota);

// 清理
await caches.keys().then(names => Promise.all(names.map(n => caches.delete(n))));

三、布局观测 API

3.1 Intersection Observer(元素可见性)

// 无限滚动 / 懒加载
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      loadMoreData();
      // 可选:观察一次后停止
      // observer.unobserve(entry.target);
    }
  });
}, {
  root: null,           // 视口
  rootMargin: '100px',  // 提前触发
  threshold: 0.1        // 10% 可见时触发
});

observer.observe(document.querySelector('.load-more-trigger'));

3.2 Resize Observer(元素尺寸变化)

const ro = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const { width, height } = entry.contentRect;
    console.log(`${entry.target.tagName}: ${width}x${height}`);
  }
});

ro.observe(document.querySelector('.chart-container'));

3.3 Mutation Observer(DOM 变化)

const mo = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    if (mutation.type === 'childList') {
      console.log('Nodes added:', mutation.addedNodes.length);
    }
  }
});

mo.observe(document.body, { childList: true, subtree: true });

四、数据交互 API

4.1 Clipboard API

// 写入剪贴板(需用户交互触发)
async function copyToClipboard(text) {
  try {
    await navigator.clipboard.writeText(text);
    showToast('已复制');
  } catch (err) {
    console.error('Copy failed:', err);
  }
}

// 读取剪贴板
async function readFromClipboard() {
  const text = await navigator.clipboard.readText();
  return text;
}

// 复制富文本
async function copyRichText(html) {
  const blob = new Blob([html], { type: 'text/html' });
  const item = new ClipboardItem({ 'text/html': blob });
  await navigator.clipboard.write([item]);
}

4.2 File System Access API

// 打开文件选择器
async function openFile() {
  const [fileHandle] = await window.showOpenFilePicker({
    types: [{
      description: 'Images',
      accept: { 'image/*': ['.png', '.jpg', '.avif'] }
    }],
    multiple: false
  });

  const file = await fileHandle.getFile();
  const content = await file.text(); // 或 file.arrayBuffer()
  return content;
}

// 保存文件
async function saveFile(content) {
  const handle = await window.showSaveFilePicker({
    suggestedName: 'document.md',
    types: [{ accept: { 'text/markdown': ['.md'] } }]
  });

  const writable = await handle.createWritable();
  await writable.write(content);
  await writable.close();
}

4.3 Web Share

async function shareContent() {
  if (navigator.share) {
    await navigator.share({
      title: 'My Awesome Article',
      text: 'Check out this article about frontend engineering',
      url: 'https://example.com/article'
    });
  } else {
    // fallback: 复制链接
    await navigator.clipboard.writeText('https://example.com/article');
  }
}

五、硬件连接 API

API支持场景
Web BluetoothChrome, Edge连接 BLE 设备(心率带、打印机)
Web USBChrome, Edge连接 USB 设备(Arduino、扫描仪)
Web SerialChrome, Edge串口通信(工业设备、3D 打印机)
Web NFCChrome AndroidNFC 标签读写
Web HIDChrome, EdgeHID 设备(游戏手柄、条码枪)
// Web Bluetooth 示例:连接心率带
async function connectHeartRate() {
  const device = await navigator.bluetooth.requestDevice({
    filters: [{ services: ['heart_rate'] }]
  });

  const server = await device.gatt.connect();
  const service = await server.getPrimaryService('heart_rate');
  const characteristic = await service.getCharacteristic('heart_rate_measurement');

  characteristic.addEventListener('characteristicvaluechanged', (event) => {
    const value = event.target.value.getUint8(1);
    console.log('Heart rate:', value);
  });

  await characteristic.startNotifications();
}

六、多媒体 API

6.1 Web Speech API

// 语音识别
const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
recognition.lang = 'zh-CN';
recognition.continuous = true;

recognition.onresult = (event) => {
  const transcript = event.results[event.results.length - 1][0].transcript;
  console.log('Speech:', transcript);
};

recognition.start();

// 语音合成
const utterance = new SpeechSynthesisUtterance('你好,世界');
utterance.lang = 'zh-CN';
utterance.rate = 1.0;
speechSynthesis.speak(utterance);

6.2 MediaRecorder

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
const recorder = new MediaRecorder(stream);
const chunks = [];

recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = () => {
  const blob = new Blob(chunks, { type: 'video/webm' });
  const url = URL.createObjectURL(blob);
  // 上传或下载
};

recorder.start();
// ...
recorder.stop();

七、身份与支付

7.1 Credential Management API

// 保存密码
await navigator.credentials.store(new PasswordCredential({
  id: 'user@example.com',
  password: 'password123',
  name: 'John Doe'
}));

// 自动登录
const cred = await navigator.credentials.get({ password: true });
if (cred) {
  await login(cred.id, cred.password);
}

// WebAuthn / Passkey
const credential = await navigator.credentials.create({
  publicKey: {
    challenge: Uint8Array.from('random-challenge', c => c.charCodeAt(0)),
    rp: { name: 'My App', id: 'example.com' },
    user: { id: Uint8Array.from('user-id'), name: 'user', displayName: 'User' },
    pubKeyCredParams: [{ alg: -7, type: 'public-key' }]
  }
});

7.2 Payment Request API

const paymentMethods = [{
  supportedMethods: 'https://apple.com/apple-pay',
  data: { version: 3, merchantIdentifier: 'merchant.example' }
}];

const details = {
  total: { label: 'Total', amount: { value: '99.99', currency: 'CNY' } },
  displayItems: [
    { label: 'Product', amount: { value: '99.99', currency: 'CNY' } }
  ]
};

const request = new PaymentRequest(paymentMethods, details);
const response = await request.show();
await response.complete('success');

八、页面通信与报告

8.1 BroadcastChannel

// 跨同源标签页通信
const channel = new BroadcastChannel('app_channel');

// 发送
channel.postMessage({ type: 'login', user: { id: 'u1' } });

// 接收
channel.onmessage = (event) => {
  if (event.data.type === 'login') {
    console.log('User logged in another tab:', event.data.user);
  }
};

8.2 Beacon API

// 可靠发送数据(页面卸载时也能发送)
window.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    const data = JSON.stringify({
      page: location.href,
      duration: Date.now() - pageStartTime,
      events: eventBuffer
    });
    navigator.sendBeacon('/analytics', data);
  }
});

8.3 Reporting API

// 自动上报 CSP 违规、Deprecation 警告、Crash
// Report-To: {"group":"default","max_age":86400,"endpoints":[{"url":"https://example.com/reports"}]}

// 也可以用 ReportingObserver 在 JS 中捕获
const observer = new ReportingObserver((reports) => {
  for (const report of reports) {
    console.log('Report:', report.type, report.body);
    // { type: 'csp-violation', body: { ... } }
  }
}, { buffered: true });

observer.observe();

九、能力地图速查

类别API支持度场景
多线程Web Workers~100%大数据计算
存储IndexedDB~100%离线数据
观测Intersection Observer~98%懒加载
社交Web Share~85%原生分享
文件File System Access~70% (Chromium)本地文件编辑
硬件Web Bluetooth~70% (Chromium)IoT
语音Web Speech~90%语音输入
身份WebAuthn / Passkey~90%无密码登录
支付Payment Request~60%原生支付
通信BroadcastChannel~95%多标签同步

参考与延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「frontend」更多文章

  1. API 设计与 BFF 层:REST、GraphQL、tRPC 选型与前后端协作
  2. WebAssembly 前端工程化实践:编译链、性能对比与混合架构
  3. 前端安全进阶:XSS、CSP、SRI 与供应链安全