跳到主要内容

微信 / WebView 环境兼容

场景

H5 页面需要在微信浏览器、App 内嵌 WebView 等环境中运行,遇到各种特有的兼容问题。

常见问题与方案

1. 环境检测

env-detect.ts
function getEnv() {
const ua = navigator.userAgent.toLowerCase();

return {
isWechat: /micromessenger/i.test(ua),
isAlipay: /alipayclient/i.test(ua),
isIOS: /iphone|ipad/i.test(ua),
isAndroid: /android/i.test(ua),
isApp: /myapp/i.test(ua), // 自有 App 的 UA 标识
isWebView:
/(; wv\))|webview|wv/i.test(ua) ||
typeof (window as any).ReactNativeWebView !== 'undefined',
};
}

2. 微信浏览器常见问题

问题原因解决方案
页面缓存不更新微信强缓存URL 加版本号/时间戳
视频自动播放失败需要微信 SDK 接入WeixinJSBridgeReady 事件
分享标题/图片不对需要微信 JS-SDKwx.updateAppMessageShareData
SPA 路由分享 URL 不变iOS 微信取的是入口 URL后端做分享签名时用入口 URL
下拉出现"此网页由..."系统行为overscroll-behavior: none
微信视频自动播放
// 微信中自动播放视频
document.addEventListener('WeixinJSBridgeReady', () => {
const video = document.querySelector<HTMLVideoElement>('#myVideo');
video?.play();
});

3. JSBridge 通信

jsbridge.ts
// 通用 JSBridge 封装
function callNative(method: string, params?: Record<string, unknown>): Promise<unknown> {
return new Promise((resolve, reject) => {
const callbackName = `_cb_${Date.now()}_${Math.random().toString(36).slice(2)}`;

// 注册回调
(window as any)[callbackName] = (result: unknown) => {
resolve(result);
delete (window as any)[callbackName];
};

// 不同环境的调用方式
if ((window as any).webkit?.messageHandlers?.[method]) {
// iOS WKWebView
(window as any).webkit.messageHandlers[method].postMessage({
...params,
callback: callbackName,
});
} else if ((window as any).AndroidBridge?.[method]) {
// Android
(window as any).AndroidBridge[method](JSON.stringify(params), callbackName);
} else {
// URL Scheme 兜底
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = `myapp://${method}?params=${encodeURIComponent(JSON.stringify(params))}&callback=${callbackName}`;
document.body.appendChild(iframe);
setTimeout(() => iframe.remove(), 100);
setTimeout(() => reject(new Error('Bridge timeout')), 5000);
}
});
}

4. WebView 白屏排查


常见面试问题

Q1: H5 与原生 App 通信有哪些方式?

答案

方式原理特点
URL Schemeiframe.src = 'myapp://...'兼容性好、有长度限制
注入全局对象App 注入 window.Bridge直接调用、需要 App 配合
postMessageWKWebView 的 messageHandlersiOS 推荐方式
prompt/console 拦截重写 prompt 等方法hack 方式、不推荐

Q2: 微信 H5 页面的 SPA 路由分享问题怎么解决?

答案

iOS 微信浏览器会将页面入口 URL(第一次打开的 URL)作为分享 URL,而不是当前路由的 URL。

解决方案:

  1. 后端签名时使用入口 URL:iOS 用 window.entryUrl(进入时记录)签名,Android 用 location.href
  2. 分享时动态设置:通过 wx.updateAppMessageShareData 设置正确的分享链接
  3. 使用 Hash 模式路由:Hash 变化不影响微信识别的 URL

相关链接