首页 > 其他分享 >字节前端监控 SDK 体积与性能优化实践

字节前端监控 SDK 体积与性能优化实践

时间:2022-10-26 17:35:32浏览次数:51  
标签:字节 前端 监听 监控 SDK 我们 性能 页面

背景

字节各类业务拥有众多用户群,作为字节前端性能监控 SDK,自身若存在性能问题,则会影响到数以亿计的真实用户的体验。所以此类 SDK 自身的性能在设计之初,就必须达到一个非常极致的水准。

与此同时,随着业务不断迭代,功能变得越来越多,对监控的需求也会变得越来越多。例如,今天 A 业务更新了架构,想要自定义性能指标的获取规则,明天 B 业务接入了微前端框架,需要监控子应用的性能。在解决这些业务需求的同时,我们会不断加入额外的判断逻辑、配置项。同时由于用户的电脑性能、浏览器环境的不同,我们又要解决各种兼容性问题,加入 polyfill 等代码,不可避免地造成 SDK 体积膨胀,性能劣化。那么我们是如何在需求和功能不断迭代的情况下,持续追踪和优化 SDK 的体积和性能的呢?

SDK 体积优化

通常而言,体积的优化是最容易拿到收益的一项。

由于监控 SDK 通常作为第一个脚本被加载到页面中,体积的膨胀不仅会增加用户的下载时间,还会增加浏览器解析脚本的时间。对于体积优化,我们可以从宏观和微观两个角度去实现。

微观上,我们会去尽可能去精简所有的表达,剥离冗余重复代码,同时尽可能减少以下写法的出现:

  1. 过多的 class 和过长的属性方法名

Class 的定义会被转换成 function 声明 + prototype 赋值,以及常用代码压缩工具无法对 object 属性名压缩,过多的面向对象写法会让编译后的 js 代码体积膨胀得非常快。例如下列代码

class ClassWithLongName {
    methodWithALongLongName() {}
}

经过 ts 转换后会变成

var ClassWithLongName = /** @class */ (function () {
    function ClassWithLongName() {
    }
    ClassWithLongName.prototype.methodWithALongLongName = function () { };
    return ClassWithLongName;
}());

压缩后代码为

var ClassWithLongName=function(){function n(){}return n.prototype.methodWithALongLongName=function(){},n}();

可以看到以上长命名都无法被压缩

如果使用函数式编程来代替面向对象编程,能够很好的避免代码无法被压缩的情况:

function functionWithLongName() {
  return function MethodWithALongLongName(){}
}

经过压缩后变成

function n(){return function(){}}

相较于 class 的版本,压缩后的代码减小了50%以上。

  1. 内部函数传参使用数组代替对象

原理同上,对象中的字段名通常不会被代码压缩工具压缩。同时合理使用 TS named tuple 类型可以保证代码可维护性。

function report(event, {optionA, optionB, optionC, optionD}: ObjectType){
}

改为

function report(event, [optionA, optionB, optionC, optionD]: NamedTupleType){
}
  1. 在不需要判断 nullable 时,尽可能避免 ?. ?? ??= 等操作符的出现。同理,尽可能避免一些例如 spread 操作符、generator 等新语法,这些语法在编译成 es5 后通常会引入额外的 polyfill。TS 会将这些操作符转换成非常长的代码,例如 a?.b会被转换成:
a === null || a === void 0 ? void 0 : a.b

过多的 nullish 操作符也是代码体积增加的一个原因。

当然,以上只列举了部分体积优化措施,还有更多优化方法要结合具体代码而议。对于我们的前端监控 SDK,为了性能和体积是可以牺牲一些开发体验的,并且由于使用 TS 类型系统,并不会对代码维护增加很多负担。

从宏观上,我们应该思考如何减少 SDK 所依赖的模块,减少产物包含的内容,增加产物的“信噪比”,有以下几个方式:

  1. 拆分文件

我们可以分离出 SDK 中不是必须提前执行的逻辑,拆分成异步加载的文件,仅将必须提前执行的逻辑加入初始脚本。同时将不同功能拆分成不同文件,业务按需加载,这样可以最大程度减少对首屏加载时间的影响。

  1. 尽可能避免 polyfill 的使用

polyfill 会显著增加产物体积,我们尽可能不使用存在兼容性的方法。甚至在不需要兼容低端浏览器环境时,我们可以不使用 polyfill。

  1. 减少重复的常量字符串的出现次数

对于多次重复出现的常量字符串,提取成公共变量。例如

a.addEventListener('load', cb)
b.addEventListener('load', cb)
c.addEventListener('load', cb)

我们可以将 addEventListener和 load 提取公共变量:

let ADD_EVENT_LISTENER = 'addEventLister'
let LOAD = 'load'
a[ADD_EVENT_LISTENER](LOAD, cb)
b[ADD_EVENT_LISTENER](LOAD, cb)
c[ADD_EVENT_LISTENER](LOAD, cb)

此段代码压缩后会变成

let d="addEventLister",e="load";a[d](e,cb),b[d](e,cb),c[d](e,cb);

我们还可以使用 TSTransformer 或者 babel plugin 来帮我们自动地完成上述过程。

标签:字节,前端,监听,监控,SDK,我们,性能,页面
From: https://blog.51cto.com/u_15204236/5798110

相关文章

  • 前端绘图方式Canvas和SVG的区别
    前端绘图方式Canvas和SVG的区别Canvas和SVG是html5中支持2种可视化技术,都是可以在画布上绘制图形和放入图片。下面来介绍和分析一下他们。一.Canvas和SVG简介1.什么是......
  • 快速了解一个新的前端项目
    转载作者:拿我格子衫来原创地址:https://blog.csdn.net/github_35631540/article/details/113880272快速浏览项目目录结构首页登陆流程,快速了解项目数据流转查看packa......
  • 美颜SDK人像抠图技术是什么?人像抠图技术是如何实现的?
    大家在刷短视频或者看娱乐直播时,会发现有些主播使用了虚拟背景,实际上他们并没有用到特别复杂的操作,只是应用了美颜SDK中的“人像抠图技术”。下面,小编就以短视频为例子,给大......
  • 麒麟系统开发笔记(九):在国产麒麟系统上搭建宇视摄像头SDK基础环境Demo
    前言  国产麒麟系统开发上,使用宇视摄像头,本篇使用宇视官网的提供的SDK,搭建基础的国产系统上宇视摄像头SDK开发化境Demo。<br>效果演示  <br>宇视SDK下载  官方......
  • 【测试全栈,先从前端开始--HTML之无序列表/有序列表】(十三)
    很久之前讲了HTML合并单元格,接下来我们说下列表,包含无序列表和有序列表。  <ul>标签表示HTML页面中项目的无序列表,一般会以项目符号呈现列表项,而列表项使用<li>标签定义。......
  • 前端页面开发工具有什么特点?
    随着数字化进程的加快发展,很多企业都倾向于选择前后端分离的架构模式,这样可以让前端和后端的工程师各司其职,提高工作效率和质量。不少客户朋友会咨询前端页面开发工具的特......
  • 前端展示中实现批量标签动态生成
    前端展示中实现批量标签动态生成使用过报表的小伙伴,经常会有条码打印、标签打印的需求,一两个标签还好处理,但很多时候我们可能需要的是几十、上百个内容的批量打印,如下图所......
  • Java反射之类的字节码对象的三种调用方式和JDBC【多测师】
    类的字节码对象:packagecom.section02;importorg.apache.log4j.Logger;importcom.section01.Student;/***@authorxiaoshu*同一个类在JVM中只存在一份字节码对象*也就是......
  • 前端一面高频vue面试题总结
    对VueSSR的理解Vue.js是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出Vue组件,进行生成DOM和操作DOM。然而,也可以将同一个组件渲染为服务端的HTML字......
  • linux 前端部署 tomcat 脚本
    前提:打包后的文件位置:/home/usr/back目的部署位置:/home/usr/prod1目的部署位置:/home/usr/prod2 在linux服务器上新增文件deploy-web.sh,并运行shdeploy-web.sh......