一、背景
1. 业务场景
登录系统->进入首页(首页主要展示一些图片)->切换至列表页面
2. 问题现象
列表页面接口一直未响应。
3. 原因排查&分析
- 由于内网、外网文件服务无法互通,首页有7个图片资源请求一直未响应(通过
<img src="xxx.png" />
标签加载),导致列表页面的请求一直处于pending状态。
- 页面切换时,未释放上一个页面的请求
浏览器对相同域名的资源请求有并发数量限制(通常为6~8个请求),为了放在服务器过载和确保用户体验。
二、解决方案
1. 将静态资源和API服务分散到不同的域名
优点
- 可解决http请求阻塞问题
缺点
- 需要更多域名支持
2. 减少网络请求
优点
- 理论上可解决此问题
- 会带来一些性能提升
缺点
- 解决此问题不适用
3. 使用图片懒加载
img标签设置loading="lazy"属性 <img src="xxxx.png" loading="lazy">
优点
- 简单,只需要设置一个属性即可
缺点
- 兼容性不是很好,IE不适用,适用于现代浏览器
- 页面图片资源过多时,除了视窗中的图片会加载,靠近视窗即将出现的图片资源也会加载,可能无法限制请求的数量
4. 页面切换时利用src=""
中断图片资源请求(推荐)
优点
- 可完美解决此问题
缺点
- img标签需要设置一个特定的属性,避免其他框架中的图片也被清除(如系统导航栏的logo)
Home.vue
<template>
<img src="xxxx1.png" />
<img src="xxxx2.png" />
<img src="xxxx3.png" />
<img src="xxxx4.png" />
<img src="xxxx5.png" />
<img src="xxxx6.png" />
<img src="xxxx7.png" />
</template>
<script>
export default {
beforeRouteLeave() { // 页面离开时中断图片资源请求
const images = container.querySelectorAll(`img[data-cancelable]`)// 此处data-cancelable可自定义配置,通过options传递
images.forEach(image => {
image.src = options.placeholder || ''
})
}
}
</script>
三、插件封装
1. 插件
ClearImageRequest.js
/*
图片请求中断插件
*/
export default {
install(Vue, options = {}) {
Vue.prototype.this.$clearImageRequest = function() {
const container = this.$el || document
const images = container.querySelectorAll(`img[data-cancelable]`)// 此处data-cancelable可自定义配置,通过options传递
images.forEach(image => {
image.src = options.placeholder || ''
})
}
Vue.mixin({
beforeRouteLeave() {
if (options.autoClear) { // 自动清除
this.$clearImageRequest()
}
}
})
}
}
2. 使用
main.js
import Vue from 'vue'
import ClearImageRequest from './plugins/ClearImageRequest.js'
Vue.use(ClearImageRequest, {
autoClear: true, // 切换页面,自动中断图片资源请求
placeholder: '', // 占位图,可选
})
// 调用方法手动中断图片资源请求
this.$clearImageRequest()