问题分析
最近遇到了一个令人头疼的兼容性问题,正常外部浏览器可以访问的一个含视频的页面。在Windows电脑微信内置的浏览器上就是会白屏,并且连视频元信息都会丢失掉。大概长这样 ↓
当时看到Windows电脑微信内置的浏览器时两眼一黑,这玩意连开发者工具都没个打开入口,这怎么排查?但是因为是用户舆情,只得硬着头皮干了。
尝试复现,发现在外部浏览器以及mac上的电脑版微信都没这个毛病。最开始以为是视频组件哪个地方用到了一个Windows微信内置浏览器不兼容的API,虽然不支持开发者工具,但也无非就是看不到报错和控制台信息,那我直接把本来想在控制台打印的东西放页面上不就完了。于是用live-server起了一个小服务,在电脑微信上用url打开,把想看的数据直接塞页面上看,但是排查了一圈发现都支持,而且直接video标签塞同一个视频的url也是一点问题没有,于是将目光瞄准了网络请求上(其实后面想想一开始的方向就应该是这个的,毕竟连元数据都没了包是网络请求挂了的,但是被其他正常请求的浏览器蒙住了双眼,以为别的浏览器都请求成功了,同一个视频的url不会因为浏览器不同出问题来着)
去想了很多地方,但是,当我打开可以正常播放视频的浏览器想抓个包的时候,被一行之前没发现的warning吸引了视线:
突然间恍然大悟,原来是在https的网页中请求了http的资源!立刻推测是外部的谷歌浏览器自动帮我把协议升级了,同时我们的cdn对http和https协议都支持,但是PC微信内置的浏览器不做升级而是直接拦截掉了!
于是立刻修改vscode中live-server插件,让它跑在https上,然后请求这个视频地址,您猜怎么着?复现了!
下面贴上代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul id="content"></ul>
<video controls>
<source
src="https://www.w3school.com.cn/i/movie.mp4"
/>
</video>
</body>
<script>
function wechatLog(container, content) {
const containerElement = document.getElementById(container);
if (containerElement) {
const li = document.createElement("li");
li.textContent = content;
containerElement.appendChild(li);
}
}
wechatLog(
"content",
"IntersectionObserver" in window
? "IntersectionObserver is supported!"
: "NO!!!!!!!!!!!!!!!!"
);
wechatLog("content", "navigator.userAgent: " + window.navigator.userAgent);
const video = document.querySelector("video");
video.addEventListener("error", (e) => {
wechatLog("content", "Video loading error: " + e.target.error.code);
});
</script>
</html>
这下搞定了,原因就是上面说的,在https的网页中请求了http的资源,外部的谷歌等浏览器自动帮我把协议升级成https访问了,且我们的cdn对http和https协议都支持,但是PC微信内置的浏览器不做升级而是直接拦截掉了,这就导致了视频直接白掉。
想了一圈,结果问题出在了最开始怀疑的网络请求上,真是的。
【附】怎么在live-server中开启https服务:
- 去这个网站搞一个自签名的证书:bkssl.com/ssl/selfsig…
- 下载证书和密钥,然后把证书后缀从.cer改成.cert。
- 去vscode的设置找到live-server,补充如下信息,记得证书路径换成自己的:
- 重启live-server,就可以看到协议变成https了,肯定会提示不安全,不过对我们看个问题还是足够了,主要是提供环境。