当前位置: 首页 > Web前端 > HTML

百度程序员开发中的陷阱规避指南(前端)

时间:2023-03-28 11:23:02 HTML

在日常的工作开发中,你遇到过哪些令人印象深刻且具有挑战性的陷阱,它们是如何产生的,又该如何避免呢?本期我们带来前端开发相关的三个问题:一个网页资源加载问题的定位过程;CSS中的z-index级联覆盖问题;CSS3transform属性对position的影响,希望能帮助大家提高技术。01定位一个网页资源加载问题的过程今天讨论的话题比较集中,就是有用户反映网页资源或者部分区域无法加载,如何查看?以及如何避免呢?1.1问题描述用户反馈页面推荐列表无法加载,可以稳定复现。1.2分析第一反应是自己复现,但是做不到。团队没有可以复现的同学,也接触不到用户。所以先理清这块区域的实现逻辑。虽然下载了该区域的HMTL,但默认是不可见的,而是依赖c.js(文件名经过简化)显示。基于此,我们怀疑:c.js及其依赖的a.js、b.js等加载速度很慢或直接失败;c.js及其依赖逻辑存在JS异常。1.3监控实现那么如何证明呢,我们需要做监控。监控需要考虑到实际场景。由于Head和Body都有外链请求,所以监控代码应该放在最上面,内联,代码要精简,这样才能最大程度的获取信息,减少对首屏的影响。window.addEventListener('error',event=>{if(event.srcElement!==window){console.log('资源加载失败,加载资源的元素是:',event.srcElement);send();}else{console.log('JSerror:',event.message);send();}},true);window.addEventListener('unhandledrejection',event=>{consterror=event.reason||{};console.log('JS错误:',error);send();});上面可以监控全局资源加载失败和JS异常,包括未捕获的PromiseRejections。另外需要定位资源,通过向上遍历得到元素的XPath,在XPath上带上id或者class属性,避免所有\`div>div>div>div\`,这让你感到困惑。上网后发现很多错误都是脚本错误。这是因为外部JS是CDN域名。浏览器执行脚本遵循同源策略,故意隐藏错误信息,防止域名信息泄露给主机域名。解决方案是给所有外部JS添加响应头。access-control-allow-origin:*如果JS资源托管在云端的CDN服务上,那么其CDN控制台会提供添加Header的功能。如果是自有服务,需要主动设置Header。这里假设使用Koa2框架,设置如下:ctx.set('Access-Control-Allow-Origin','*');然后给CDN域名的所有script元素添加crossorigin属性,如:但是发现它在Chrome浏览器中有效,你可以得到真正的错误堆栈。不幸的是,Safari浏览器不支持这种机制,仍然只会出现脚本错误。为了让Safari获得真正的错误,外部链接需要在同一个域中。所以有一种方法是在www.a.com的Nginx中做一层代理转发,即把https://www.a.com/static/a.js转发到https://cdn.a。com/static/a.js。但这样一来,就失去了CDN访问就近的优势,不适合归一化。不过在定位用户问题时,暂时将用户访问切换到https://www.a.com/static/a.js。那么如何监控慢加载,可以在onload事件之后获取慢资源。constlist=performance.getEntriesByType('resource');constlen=list.length;constslowList=[];for(leti=0;i1000){slowList.push(timing);}}发送(慢列表);报告的信息还包括每个请求的TCP耗时和下载时间。有关详细信息,请参阅Resource\_Timing\_API规范(https://developer.mozilla.org...\_Timing\_API/Using\_the\_Resource\_Timing\_API)。需要注意的是,API信息受CORS(https://developer.mozilla.org...)影响,资源获取数据必须设置如下响应头,否则很多的值字段为0。Timing-Allow-Origin:*通过分析这些数据,我们可以知道资源的耗时过程。在这里,我们完全可以参考Chrome开发者工具提供的Timing子面板来了解关键期的耗时情况。比如同一个域名有6个并发请求的限制。如果资源请求较多,则可能处于stalled(暂停等待)状态。这些阶段的可能原因分析,请参考Chrome说明。由于有些图片在页面中的位置很难确定,所以需要获取它们的XPath,如何获取呢?对于加载图片的img标签,可以快速获取://timing.name为资源地址,适合constimg=document.body.querySelector('img[src="'+timing.name+'"]');constxpath=getxpath(img);附加信息的获取,其实除了问题信息本身,用户当时的环境信息也很重要,比如1.performance.memory:获取内存使用信息;2.navigator.connection:用户连接状态,不幸的是,这个API并不准确;如果是APP中的页面,可以调用终端能力获取用户的网络类型和网速。1.4数据分析上线后,用户仍然访问缓慢。根据日志,用户并没有报任何JS错误,但是根据慢资源日志,发现大量资源加载时间超过1s,有的资源甚至达到10s,耗费了大量资源连接建立阶段的时间。看来问题没那么简单,那么用户资源加载慢怎么解释呢?用户局域网环境差?接入载体质量差?插件影响?CDN问题?只有CDN才能解决这些问题。我们先获取用户访问https://www.a.com的服务器端日志,获取用户IP。联合云CDN服务,根据用户IP,没有发现任何CDN访问日志。但是从日志来看,用户确实请求了很多JS,并没有全部缓存到本地。因此,用户IP可能不是访问CDN的IP。有使用代理的情况。所以想通过其他信息获取用户的CDN日志来确定访问CDN的IP。思路是根据用户UA、请求地址等不准确的信息获取CDN日志,但由于检索到的日志量大,无法判断哪些日志属于该用户;并且:1、CDN域名一般都是无cookie的域名,没有TRACEID;2、网页不能为脚本/链接资源请求头设置Traceid;3、前端目前无法获取到CDNTCP连接IP;综上所述,除用户IP外,各种精准定位信息均无效。所以这一步很难。幸运的是,我能够联系到用户并询问是否使用代理。结果:我确实用了代理,根据用户代理,实测代理很慢,甚至加载超时,代理请求去了香港服务器。通过代理出口IP,最终从海外CDN获取到用户访问日志。同时也确认用户配置所有*.a.com请求不使用代理,所以服务器能拿到的IP是用户IP,而CDN拿到的是代理出口IP。1.5小结Web能力终究是有限的,但是辅助信息充足,全链路协同,Cases的定位过程会更加有效。虽然这种情况归咎于用户的代理配置不合理,但也可以针对这种情况进行技术优化。例如任何首屏内容不依赖外部链接显示,减少核心逻辑JS量,提高资源缓存率等。02CSS2.1中的z-index级联覆盖问题含义z-index属性指定[元素及其子元素的zorder],[zorder]可以确定元素被覆盖时哪个元素在最上面。通常具有较高z-index的元素会覆盖较低的元素。该属性指定了两个东西:当前元素的堆叠顺序当前元素是否建立新的堆叠上下文2.2属性值默认值:z-index:auto;整数值:z-index:<整数>;继承:z-index:继承;2.3基本特性在CSS2.1时代,需要结合定位元素使用;如果定位元素的z-index没有嵌套(平行):先到先得;以较大者为准(z-index大小比较);如果定位元素z-index是嵌套的:祖先优先原则(前提:z-index是一个值,不是auto)以上就是z-index的基本介绍。当业务越来越复杂,各种弹窗,toasts,浮层和各种组件,多人协同业务开发:老业务写一个z-index:5000;同学B调用了一个全局弹出层,原本设置的是100,如果要覆盖整个世界,就把z-index改成10000;C同学调用了一个toast,本来设置为2000,想覆盖弹出层,把z-index改成100000;无限变化,为了避免出现这种情况,减少连续覆盖的情况,z-index的值应该如何指定;constKEY='_tbv_z_index_';functioninitZIndex$(){return(window[KEY]=10000);}//初始化,只能调用一次functiononce(fn){constflag=true;返回函数(){if(flag){flag=false;constargs=Array.prototype.slice.call(arguments,0);fn.apply(args);}};}constinitZIndex=once(initZIndex$);//外部调用&支持复位函数zIndex$(zIndex){if(zIndex){return(window[KEY]=zIndex);}return(window[KEY]+=1);}//组件挂载时触发+1constzIndex=zIndex$();注意:还是要规范z-index的配置,不要滥用和滥用随机分配,根据依赖规则合理使用;03CSS3transform属性对position的影响CSS3中引入Transform,定义了元素在二维或三维空间中的旋转、缩放、平移等行为,也可以利用合成层原理实现GPU加速提高页面动画的流畅度。不过,transform并不是“省油的灯”(我不是说它不好,我很喜欢)。在增强页面交互效果的同时,也存在一些容易让人踩坑的“副作用”。position:fixed实现固定定位的效果,元素不跟随滚动条滚动,普通元素的overflow属性无法切割,所以在一些需要固定头部和固定浮动的场景下非常有用按钮。但是当fixed遇到transform,就不再那么“强硬”了,而是退化成了position:absolute的效果。当外层没有transform效果时,固定定位元素的包含块就是根元素,可以近似看成是元素,所以固定元素可以实现相对视口定位的效果。当元素设置为转换时,将创建一个新的包含块。如果设置了固定定位的元素内部有元素,那么固定元素的包含块就不再是根元素,而是变成了被设置为transform的元素。如果在开发过程中,发现position:fixed元素随页面滚动,可以查看fixed元素外层是否有元素设置了transfrom。除了containingblocks,transform还会生成一个新的栈上下文(stackcontext),使得元素的内部和外部z-index相互独立,低z-index元素的级别比它高高z-index元素:推荐阅读:百度工程师教你快速提升研发效率的秘诀百度一线工程师谈千变万化的云原生【技术加油站】揭秘百度智能测试大规模落地【技术加油站】浅谈百度智能测试的三个阶段