1 背景
灯塔是贝壳找房前端架构组推出的一款前端监控系统, 最近和业务方对接时, 被问到了这样一个问题:
为什么前端监控要用 GIF 打点?
这个问题很有意思。我们知道,目前主流的前端监控(百度统计/友盟/谷歌统计)都在用 GIF 进行打点。但是,为什么这些系统都会使用 GIF,难道是因为没有其他的解决方案吗?
这得从前端监控的原理说起。
2 前端监控的原理
所谓的前端监控,其实是在满足一定条件后,由 Web 页面将用户信息(UA/鼠标点击位置/页面报错/停留时长/etc)上报给服务器的过程。一般是将上报数据用 url_encode(百度统计/CNZZ)或 JSON 编码(神策/诸葛 io)为字符串,通过 url 参数传递给服务器,然后在服务器端统一处理。
这套流程的关键在于:
1)能够收集到用户信息;
2)能够将收集到的数据上报给服务器。也就是说,只要能上报数据,无论是请求 GIF 文件还是请求 js 文件或者是调用页面接口,服务器端其实并不关心具体的上报方式。
向服务器端上报数据,可以通过请求接口,请求普通文件,或者请求图片资源的方式进行。为什么所有系统都统一使用了请求 GIF 图片的方式上报数据呢?
可能的方式
3 为什么主流方案用 GIF 上报数据
解答这个问题,要用排除法。
首先,为什么不能直接用 GET/POST/HEAD 请求接口进行上报?
这个比较容易想到原因。一般而言,打点域名都不是当前域名,所以所有的接口请求都会构成跨域。而跨域请求很容易出现由于配置不当被浏览器拦截并报错,这是不能接受的。所以,直接排除。
可能的方式_排除接口请求
其次,为什么不能用请求其他的文件资源(js/css/ttf)的方式进行上报?
这和浏览器的特性有关。通常,创建资源节点后只有将对象注入到浏览器 DOM 树后,浏览器才会实际发送资源请求。反复操作 DOM 不仅会引发性能问题,而且载入 js/css 资源还会阻塞页面渲染,影响用户体验。
但是图片请求例外。构造图片打点不仅不用插入 DOM,只要在 js 中 new 出 Image 对象就能发起请求,而且还没有阻塞问题,在没有 js 的浏览器环境中也能通过 img 标签正常打点,这是其他类型的资源请求所做不到的。
所以,在所有通过请求文件资源进行打点的方案中,使用图片是最好的解决方案。
可能的方式_排除文件请求
那还剩下最后一个问题,同样都是图片,上报时选用了 1x1 的透明 GIF,而不是其他的 PNG/JEPG/BMP 文件。
这是排除法的最后一步,原因其实不太好想,需要分开来看。
首先,1x1 像素是最小的合法图片。而且,因为是通过图片打点,所以图片最好是透明的,这样一来不会影响页面本身展示效果,二者表示图片透明只要使用一个二进制位标记图片是透明色即可,不用存储色彩空间数据,可以节约体积。因为需要透明色,所以可以直接排除 JEPG(BMP32 格式可以支持透明色)。
然后还剩下 BMP、PNG 和 GIF,但是为什么会选 GIF 呢?
因为体积!
下方是 1x1 像素透明图,最小的 BMP/PNG/GIF 文件结构。
BMP:
BMP
PNG:
PNG
GIF:
GIF
可以看到,最小的 BMP 文件需要 74 个字节,PNG 需要 67 个字节,而合法的 GIF,只需要 43 个字节。
同样的响应,GIF 可以比 BMP 节约 41%的流量,比 PNG 节约 35%的流量。这样比较一下,答案就很明显了。
上报数据,显然 GIF 才是最佳选择。
可能的选择_最终结果
##4 总结
前端监控使用 GIF 进行上报主要是因为:
没有跨域问题;
不会阻塞页面加载,影响用户体验;
在所有图片中体积最小,相较 BMP/PNG,可以节约 41%/35%的网络资源。
最后,感谢提供支持的各位大佬:
@周晨 提出了这个问题;
@大董 指出加载图片不需要操作 DOM,性能更好;
@CC 老师 指出在没有 JS 的环境中,只有图片打点才能正常工作(GET 方式需要用户触发);
@丸九 介绍了各种图片格式的特点,解释了为什么一定要 1 像素透明图;
@伍子胥 查阅了网上的资料,并确认关键因素:文件体积。
作者介绍:
大布(企业代号名),目前负责贝壳找房前端开发工作。
本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。
原文链接:
https://mp.weixin.qq.com/s/v6R2w26qZkEilXY0mPUBCw
评论 1 条评论