在 React Native 0.74 项目中如何启用“websockets: false”回退到长轮询?
解读
国内 React Native 0.74 项目普遍使用 pouchdb-browser 或 pouchdb-react-native 作为 CouchDB 同步端。
由于 Metro 打包器对 WebSocket 原生模块 的裁剪,以及国内部分机型(华为、荣耀)对 WebSocket 的省电策略,首次连接失败率可达 15%。
面试官真正想考察的是:
- 你是否知道 pouchdb-adapter-http 的底层传输链;
- 能否在 0.74 新架构(TurboModules + Fabric) 下,把 WebSocket 关闭并强制降级到 HTTP 长轮询,同时保证 同步性能不崩溃;
- 是否熟悉国内网络环境下的 反向代理(nginx + ws→wss) 与 CDN 缓存头 冲突问题。
知识点
- pouchdb-core 在创建 PouchDB 实例时,通过 ajax 字段注入自定义请求库;
- pouchdb-adapter-http 优先检测全局
WebSocket,若显式传入opts.websockets = false,则直接跳过 ws 协议,改用 ajax({ timeout, heartbeat }) 实现长轮询; - React Native 0.74 的 hermes 引擎已移除
window.WebSocket全局变量,但 react-native-community/netinfo 仍会在某些时机提前加载 WebSocket polyfill,导致 opts.websockets = false 被覆盖; - 国内 OSS 镜像(淘宝、华为)对 ** pouchdb 7.3.1** 的 dist 文件做了 gzip 双重压缩,若直接
import PouchDB from 'pouchdb',会触发 DEV 下的 source-map 告警,间接拖慢长轮询心跳。
答案
-
锁定依赖版本,禁止自动升级 WebSocket 相关包
package.json 中追加
"resolutions": { "ws": "~7.5.9", "react-native-polyfill-globals": "~3.0.1" } -
在入口文件 index.js 最顶部,先于任何 import 抹掉 WebSocket
global.WebSocket = undefined; // 彻底移除 WebSocket 全局 delete global.__PouchDBWebSocket; // 防止 pouchdb 运行时再次挂载 -
创建自定义 ajax 包装,显式关闭 websockets 并开启长轮询心跳
import PouchDB from 'pouchdb-core'; import HttpAdapter from 'pouchdb-adapter-http'; PouchDB.plugin(HttpAdapter); const ajax = ({ url, ...rest }) => { return fetch(url, { ...rest, timeout: 30000, // 国内 4G 到 5G 切换时容忍 30s headers: { ...rest.headers, 'X-WS-Fallback': '1', // 给 nginx 日志打标,方便灰度 }, }); }; const localDB = new PouchDB('rn_cache'); const remoteDB = new PouchDB('https://your-couch-cn-east-1.myqcloud.com/db', { adapter: 'http', ajax, websockets: false, // 关键开关 skip_setup: true, heartbeat: 10000, // 10s 心跳,符合腾讯云 CLB 空闲超时 60s }); localDB.sync(remoteDB, { live: true, retry: true, back_off_function: delay => Math.min(delay * 2, 60000), // 指数退避,封顶 1min }); -
验证回退是否生效
在 Chrome DevTools → Network 中过滤_changes?feed=longpoll,应看到 持续 25s 左右 的 pending 请求;若出现101 Switching Protocols则回退失败,需检查 步骤2 是否被热重载覆盖。
拓展思考
-
如果面试官追问“长轮询仍出现 502”,可答:
国内云厂商 CLB 默认 60s 断开,需在 nginx 增加
proxy_read_timeout 3600s; proxy_send_timeout 3600s;
并在 location /db/_changes 中单独 关闭缓存proxy_buffering off;。 -
若业务需要 双向实时,但 WebSocket 被运营商 QOS 降速,可引入 pouchdb-replication-stream 做 增量快照 + 断点续传,在 React Native 0.74 的 JSI 线程 中通过 C++ TurboModule 直接写文件,绕过 JavaScript 层长轮询性能瓶颈。