img
2024年04月24日
一、认识
我们通常选用 1px
的透明 GIF
作为图片地址,上报埋点数据。
二、对比
2.1 img vs ajax
使用ajax
的话,会存在跨域的问题。而且数据上报前端主要是负责将数据传递到后端,并不过分强调前后端交互。因此我们可以通过一些支持跨域的标签去实现数据上报功能。script
,link
,img
就是我们上报的数据的最好对象
2.2 img vs link & script
当我们使用script
和link
进行埋点上报时,需要挂载到页面上,而反复操作dom
会造成页面性能受影响,而且载入js/css
资源还会阻塞页面渲染,影响用户体验,因此对于需要频繁上报的埋点而言,script
和link
并不合适。
对于 img
标签来说, 不仅不用插入DOM
,只要在js
中new
出Image
对象就能发起请求,而且还没有阻塞问题,在没有js
的浏览器环境中也能通过img
标签正常打点。
2.3 gif vs png & jpeg & bmp
-
在所有图片中,
GIF
图片简单、安全; -
GIF
相比PNG/JPG
体积最小(最小的BMP
文件需要74
个字节,PNG
需要67
个字节,而合法的GIF
,只需要43
个字节);
同样的响应,GIF
可以比BMP
节约41%
的流量,比PNG
节约35%
的流量。GIF
才是最佳选择。
2.4 img report schema summarize
-
img
没有跨域限制 -
不会携带
cookie
-
无需挂载到页面上,反复操作
dom
-
img
的加载不会阻塞html
的解析,但img
加载后并不渲染,它需要等待Render Tree
生成完后才和Render Tree
一起渲染出来
所以,我们通常使用 1px
的透明 GIF
作为 img
标签去做埋点上报,img
标签加载并不需要挂载到页面上,基于js
去new image()
,设置其src
之后就可以直接请求图片。
三、上报
- 前端
- 服务端
function buryingPointByImg(type) {
const img = new Image();
img.src = `/server/buryingPoint/img?type=${type}&url=img&device=pc`
}
static async img(ctx) {
const { url, type, device } = ctx.request.query;
const buryingPoint = new BuryingPoint({
url,
type,
device,
});
await buryingPoint.save();
ctx.set('content-type', "image/gif");
ctx.body = "https://bolawen.github.io/resource/image/gif/gif_1px_transparent.gif"
}