程序员开发避坑指南(前端篇)-yb体育官方

yb体育官方-亚博平台app下载 我们 服务 网站建设 移动应用 案例 资讯 联系
业务专线:

期待聆听您的声音

15989169178

不忽悠,不作恶,不欺诈;敬天理,存良知,思利他。
服务网点:广州 深圳 佛山 粤西

与我们一起分享美好

程序员开发避坑指南(前端篇)

发布时间:2022-06-02 发布作者:睿思设计 查阅次数:124次 标签:
日常工作开发中,遇到哪些坑是让你印象深刻且具有挑战的,它们是怎么产生的,我们该如何避免?本期我们带来与前端开发相关的三个问题:一次网页资源加载问题的定位过程;css中的z-index层叠覆盖问题;css3 transform 属性对 position 的影响,希望能为你的技术提升助力。


01


一次网页资源加载问题的定位过程

今天讨论的话题比较聚焦,就是有用户报web页面资源或局部区域加载不出来的问题,该如何查?又该如何避免?


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('js报错:', event.message);        send();    }}, true);window.addeventlistener('unhandledrejection', event => {    const error = event.reason || {};    console.log('js报错:', error);    send();});

上述可以监控到全局的 资源加载失败 和 js异常,包括未捕获的promise rejection。此外,还需定位资源,通过向上遍历获取元素的xpath,xpath上带上id或class属性,避免全都是`div>div>div>div`,而摸不着头脑。

上线后发现,有不少错误都是script error,这是因为外链js都是cdn域名。浏览器对于脚本执行遵守 same-origin policy ,为避免域名信息泄漏给宿主域名,特意隐藏错误信息。
亚博平台app下载的解决方案是给所有外链js加上响应头。
access-control-allow-origin: *
js资源若托管在云上cdn服务,那么其cdn控制台都会提供增加header功能。
若是自有服务,就需要主动设置header。这里假设使用koa2 框架,设置如下:
ctx.set('access-control-allow-origin', '*');
然后给所有该cdn域名的script元素增加crossorigin属性,如:

但发现其在chrome浏览器是生效的,可以拿到真实错误堆栈。可惜,safari浏览器不支持此机制,依然只能拿到script error。为了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事件后获取慢资源。
const list = performance.getentriesbytype('resource');const len = list.length;const slowlist = [];for (let i = 0; i < len; i  ) {     const timing = list[i];     // 大于1s     if (timing.duration > 1000) {         slowlist.push(timing);     }}send(slowlist);

上报信息也包含了每个请求的tcp、下载等耗时,详细可见resource_timing_api规范(https://developer.mozilla.org/en-us/docs/web/api/resource_timing_api/using_the_resource_timing_api)。
要注意的是,该api信息受到cors (https://developer.mozilla.org/en-us/docs/glossary/cors)影响,必须给资源设置如下响应头才能拿到数据,否则很多字段取值都是0。
timing-allow-origin: *
通过分析这些数据,我们可以知道资源耗时过程,这里可以充分参照chrome开发者工具提供的timing子面板,了解关键时段耗时。比如同域名6个并发请求限制,若资源请求较多,则可能处于stalled(挂起等待)状态。这些阶段可能原因分析参考chrome说明。


由于有些图片在页面内不好确定位置,因此需要获取其xpath,如何获取呢?对于img标签加载图片,可以快速获取:
// timing.name就是资源地址,适合const img = document.body.queryselector('img[src="'   timing.name   '"]');const xpath = 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.web页面无法给script/link资源请求头设置traceid;
3.前端目前无法拿到cdn tcp建连ip;
综上,除了用户ip,种种精确定位信息都无效。因此这一步举步维艰。

好在能联系上用户,咨询是否使用代理,结果:确实使用了代理,且根据用户代理,实测代理非常慢,甚至加载超时,其代理请求走了香港服务器。通过代理出口ip,最终从海外cdn捞取到了用户访问日志。同时也确认,用户将所有 *.a.com 请求配置不使用代理,所以服务端能拿到的ip是用户ip,而cdn拿到的是代理出口ip。


1.5 总结


web能力终是有限,但通过足够的辅助信息,以及全链路协作,在定位case过程中也会事半功倍。该case虽然归因于用户不合理代理配置,但也可基于此场景做技术优化。如任何首屏内容不依赖外链展现,减少核心逻辑js体积,增加资源缓存率等。



02


css中的z-index层叠覆盖问题



2.1 含义


z-index属性指定了元素及其子元素的【z顺序】,而【z顺序】可以决定当元素发生覆盖的时候,哪个元素在上面。通常一个较大的z-index值的元素会覆盖较低的那一个。

属性指定两件事:


2.2 属性值

2.3 基本特性


以上为z-index的基本介绍。

当业务越来越复杂,多种弹窗、toast、浮层各种组件,多人协同业务开发的情况下:


const key = '_tbv_z_index_';function initzindex$() {    return (window[key] = 10000);}// 初始化,只能被调用一次function once(fn) {    const flag = true;    return function () {        if (flag) {            flag = false;            const args = array.prototype.slice.call(arguments, 0);            fn.apply(args);        }    };}const initzindex = once(initzindex$);// 外部调用&支持重置function zindex$(zindex) {    if (zindex) {        return (window[key] = zindex);    }    return (window[key]  = 1);}// 组件mount时触发 1const zindex = zindex$();


注意:还是要规范z-index的配置,不要乱用滥用随意赋值,根据依赖规则合理使用;




03

css3 transform 属性对 position 的影响


css3中引入了transform,定义了在二维或三维空间中元素的旋转、缩放、平移等行为,还能利用合成层原理开启gpu加速,提升页面动画的流畅度。然而transform也不是「省油的灯」(并没有说它不好的意思,我就很喜欢它),增强了页面交互效果的同时它也有一些「副作用」容易让人踩坑。


position: fixed 实现了固定定位的效果,元素不追随滚动条进行滚动,普通元素的overflow属性也无法对其进行裁剪,因此在一些需要固定头部、固定悬浮按钮的场景中十分好用。


但fixed遇上transform时表现的就不再那么「强硬」,反而退化成了position: absolute的效果。在外层没有transform影响时,固定定位元素的包含块是根元素,可以近似认为是元素,因此fixed元素可以实现相对视口定位的效果。而当元素设置了transform时,便会创建一个新的包含块(containing block),如果该元素的内部有元素设置了fixed定位,那么该fixed元素的包含块便不再是根元素,而变成了被设置了transform的元素。如果在开发过程中发现设置了position:fixed的元素随着页面滚动了,就可以看下fixed的元素外层是否有元素设置了transfrom。


除了包含块之外,transform还会生成新的层叠上下文(stack context),使得元素内部和外部的z-index相互独立,出现低z-index元素层级比高z-index元素还高的情况:

公文为什么要用“仿宋_gb2312”字体?

我们的位置

广州 广州市黄埔区科学大道18号芯大厦

深圳 深圳市南山区大冲国际中心九楼

粤西 茂名市茂南区油城三路粤西创业创新孵化基地b110

亚博平台app下载的服务

网站及移动应用 高端品牌网站 app开发 小程序开发 微信运营

系统应用开发 oa/erp/crm/hr系统开发

了解我们

yb体育官方的简介 联系亚博平台app下载 我们的案例 新闻资讯

© 2009-2022 广州睿网信息科技有限公司 yb体育官方的版权所有 

网站地图