Grafana分享多个panel时ifream重复引用静态资源问题的记录

目录

1.问题描述

2.解决思路

2.1 使用load

2.2 代理模式

2.3 父页面引入公用js

总结

小插曲

参考文献


1.问题描述

有一个监控平台的项目,数据界面化展示使用Grafana,但是又不能完全使用Grafana作为前台,还有自己系统中相关业务页面,关于数据展示页只能通过嵌入Grafana的panel的方式来实现,当然,如果页面的所有视图全部都可以通过Grafana来配置的话,那可以直接嵌入整个dashboard的方式来实现,这种情况就不用考虑今天要说的问题了。但项目中的数据视图有自己开发的,也有使用Grafana的,所以一个视图中是混合着来的,只能引入多个Grafana的panel分享链接。

Grafana的panel分享链接如下

可以明显看到,这是一个iframe串。

当一个页面嵌入了多iframe的时候,每一个iframe都会下载对应的静态js和css,以Grafana为例,会有两个比较大的js要下载,一个是3.6M的vendor.js,一个是1.7M的app.js。如果有6个页面,那就会下载6次,这体验实在是太糟糕了。

2.解决思路

最直观的想法就是有没有什么办法让这些iframe之间共享缓存?但是通过加载的过程,可以看到它们全部都是自己下载自己的,并没有使用缓存,加载完毕后,F5刷新,会看到是走缓存了,但是第一次的体验始终是糟糕和不够优雅的。

有以下几种思路

2.1 使用load

既然iframe每次都要加载静态资源,那么如果我们使用jquery的load来加载页面,所有被load的页面都在一个页面中,那css/js是否就可以使用缓存了呢?

尝试之后发现,这种方式不适合目前的情况,因为会引起跨域请求的问题,Grafana的panel面板url和前台程序是两套,必然会引起跨域请求,所以放弃了。

jquery的load主要用于大页面分割,加载不同小页面的情况下,把每一块单独写到独立的html中,然后load进来,都是同一个项目域下的页面才行。

2.2 代理模式

尝试使用中间代理的方式,通过代理缓存公用js,iframe请求代理,然后代理和前台程序部署在一块。直观上感觉这样好像是不错的解决方案,因为代理会缓存那些js和css,不用每个iframe再远程请求了。

但实际上,这种方式没不能带来多大的优化效果,因为通过浏览器的调试模式可以看到,每个iframe还是会各自加载各自的静态资源,你无法避免每个iframe的请求,即这个缓存是代理那里,并没有到浏览器中,所以没有太大的效果。

2.3 父页面引入公用js

尝试把比较大的两个js拿出来,直接在父页面引入,然后让iframe使用父页面的缓存,这种方案是参考这里的。

首先要说的是,这种方案是可行的,但是有一些注意事项。

我写了一个简单的例子进行测试,如下

<body>
    <div style="padding:1rem;border: 1px solid #be590a; ">
        <iframe id="f1" src="http://192.168.1.116:3000/d-solo/xkqZOmqiz/zai-xian-jie-ru-ye-wu-shi-tu?orgId=1&panelId=6" width="300px" height="300px;"></iframe>
    </div>
    <div style="padding:1rem;border: 1px solid #be590a; ">
        <iframe id ="f2" src="http://192.168.1.116:3000/d-solo/xkqZOmqiz/zai-xian-jie-ru-ye-wu-shi-tu?orgId=1&panelId=8" width="300px" height="300px;"></iframe>
    </div>
    <script type="text/javascript" src="../assets/js/jquery-1.9.1.min.js"></script>
    <script type="text/javascript" src="http://192.168.1.116:3000/public/build/vendor.d3fff3b4305980ef147d.js"></script>
    <script type="text/javascript" src="http://192.168.1.116:3000/public/build/app.d3fff3b4305980ef147d.js"></script>
</body>

按照上面这样写,运行起来之后,F12,查看f1和f2这两个iframe并没有走缓存,还是各自走各自的。

为什么不行?

造成不走缓存的原因在于,父页面加载到iframe时,iframe是独立的,浏览器新开一个线程,独立去渲染iframe,同时父页面继续渲染,也就意味着,iframe在渲染的时候,父页面中引入的全局js还没有缓存到浏览器中,那么iframe中自然是无法使用缓存了。

改成如下方式,就可以了

<body>
    <div style="padding:1rem;border: 1px solid #be590a; ">
        <iframe id="f1" src="" width="300px" height="300px;"></iframe>
    </div>
    <div style="padding:1rem;border: 1px solid #be590a; ">
        <iframe id ="f2" src="" width="300px" height="300px;"></iframe>
    </div>
    <script type="text/javascript" src="../assets/js/jquery-1.9.1.min.js"></script>
    <script type="text/javascript" src="http://192.168.1.116:3000/public/build/vendor.d3fff3b4305980ef147d.js"></script>
    <script type="text/javascript" src="http://192.168.1.116:3000/public/build/app.d3fff3b4305980ef147d.js"></script>
    <script type="text/javascript">
        window.onload=function(){
            document.getElementById('f1').src="http://192.168.1.116:3000/d-solo/xkqZOmqiz/zai-xian-jie-ru-ye-wu-shi-tu?orgId=1&panelId=6";
            document.getElementById("f2").src="http://192.168.1.116:3000/d-solo/xkqZOmqiz/zai-xian-jie-ru-ye-wu-shi-tu?orgId=1&panelId=8";
        }
    </script>
</body>

即:等父页面加载完毕后,此时静态资源已经在浏览器中缓存了,再动态指定iframe的src,iframe加载时候会先从缓存取,重新运行页面,F12,能看到iframe的请求已经走缓存,大功告成!

总结

所谓缓存,其实是浏览器缓存,和iframe是没关系,只要浏览器有这个缓存,请求的时候不论是什么页面,无论是那个iframe,只要请求资源的域不变,浏览器中有缓存,就直接从缓存中取了,一切并不像想象的那么神秘!

小插曲

再按照上面的方式确认可以走缓存之后,同事的电脑却一直不行,不管怎样每个iframe每次都会各自加载各自的,想来想去,是不是浏览器兼容性的问题?但是同样都是谷歌浏览器,没道理啊。

然后打开同事的浏览器,F12

看到如上设置,笑哭了~~。

Disable cache 禁用cache,那自然是无法使用浏览器缓存了,一般情况,在调试模式的时候,都会这样设置,免得每次都强制刷新,但是这次在这个问题上却刚好适得其反了。

参考文献

【1】一个页面多个ifram加载JS问题

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值