前端埋点数据上传方式

213 阅读3分钟

背景

前端监控系统需要将收集到的数据发送到后端服务器保存,首先我们想到的是利用AJAX请求向后端发送数据保存,但是有以下问题:

  • AJAX请求体积仍然相对较大,在频繁传输的数据请求中使用是非常损耗性能的
  • 监控数据的前端代码通常是与服务器不在同一个域名下的,这意味着后端工程师需要处理跨域请求
  • 将收集到的数据发送到后端后并不需要关心返回值

我们除了基本的AJAX发送请求之外,我们还可以通过加载资源的方式上报,比如通过“script”和“link”标签,通过在字符串拼接方式在“src”属性后拼接数据,然后将标签添加到html内,就可以实现向后端发送数据,这解决了跨域问题,但是在浏览器解析这两种标签资源时候,是会阻塞页面渲染的,尤其是在用户使用页面的时候就会出现卡顿或者响应时间过长的情况。在漫长的检索当中,我发现了用Image对象发送数据的方法。


使用Image对象上传数据

使用Image发送请求是个例外,它并不需要将元素插入到html中才会发送请求,只需要创建它就立即根据对象内部src发送请求获取图片,这意味着它不仅可以没有跨域限制,而且也不会阻塞渲染,影响用户。

通常用法

Image的原始用法是这样的

   var img = new Image();
   var src = 'http://localhost:80/img/img_test.gif'
   img.src = src;

效果如下:

image.png 然后我们可以对图片跟进一步的处理,这部分我听说对于前端AI人脸识别方面应用比较广泛

接下来就是我们的用法:

        var params = {};
        params.domain = document.domain
        params.title = document.title
        params.sh = window.screen.height
        params.sw = window.screen.width
        params.cd = window.screen.colorDepth

        params.lang = navigator.language
        //拼接参数串
        var args = '';
        for (var i in params) {
            // alert(i);
            if (args != '') {
                args += '&';
            }
            args += i + '=' + params[i];           //将所有获取到的信息进行拼接
        }
        //通过伪装成Image对象,请求后端脚本
        var img = new Image(11);
        var src = 'http://localhost:80/sdk.gif?args=' + encodeURIComponent(args);
        img.src = src;

params对象模拟我们收集到的数据,并将其用“&”号分割来进行拼接,再将他们拼接到图片请求的后面, 然后我们后端使用node.js部署,接口和效果如下:

image.png 可以看到我们在图片上的参数已经发送出去了,后端可以根据“&”进行分割,然后获取数据,而前端这边因为返回的是空,所以Image对象也就接收不到任何东西,因此是啥都没有,不像上面我们正常使用那样,上面我们使用的时候我服务器确实部署有该路径的静态资源,也能正常返回图片数据,所以上面的Image是有图片可以预览的,前端效果如下:

image.png


如果不是gif格式会怎么样

对于一个最小的数据,PNG是67字节,BMP是74字节,而GIF是43字节,所以GIF可以帮我们节省流量,所以GIF格式是最佳的上传载体