vue3 项目部署到线上环境,初始进入系统,页面卡顿大概一分钟左右,本地正常无卡顿。localStorage缓存1MB数据导致页面卡顿。

使用vue3进行项目开发,前端框架使用jeecg-boot进行开发,项目初期,打包部署到生产环境,无异常。某天,进行前端项目打包部署到生产环境,突然出现异常情况,部署到线上环境,初始进入系统,页面卡顿大概一分钟左右,但是本地开发环境正常无卡顿。

于是使用各种工具,对系统进行分析,浏览器任务管理器,查看系统运行情况;F12查看是否有接口长耗时等问题;使用监控软件监控浏览器资源消耗情况;linux文件句柄打开限制;nginx配置等。

异常情况如下图所示:

1、异常情况分析

a.接口异常可能情况分析

运用各种工具排查观察,在开发者模式下,F12查看请求耗时情况,发现接口请求耗时无异常,都在毫秒(ms)级别能做出响应,但是接口response无响应返回值,于是怀疑后端接口问题,于是使用postman单独调用测试后端接口,发现接口响应无异常,于是排除后端服务问题。

在查看所有请求,包括静态资源,查看所有请求资源时,发现部分静态资源处于pendding状态,于是怀疑静态资源慢,因此也拷贝该资源链接,单独请求,发现资源请求无异常,也能在毫秒(ms)响应。于是排除静态资源问题。多次观察发现,系统初次登录后,进入后端管理页面,需要加载大约1分钟左右时间,请求资源链接178个,但是每次刷新系统或者登录系统时,发现请求资源链接58个左右时,就会存在部分pendding状态的请求资源,总是怀疑该部分资源请求缓慢,但是对于pendding状态的请求资源单独浏览器访问,也能在毫秒(ms)响应。于是排除网络及资源请求缓慢问题。

b.nginx配置分析

怀疑nginx配置问题导致,于是检查nginx配置,部署上线不使用缓存等,仍不能有效解决。于是在本地部署NGINX,并打包项目部署在本地进行排查分析,发现和线上存在相同情况,基本排除nginx问题。

c.缓存数据分析

通过第1点分析,怀疑是因为业务逻辑处理导致系统处于卡顿,没有进行异步操作,导致主线程阻塞导致页面请求资源不能响应。于是想到可能是因为在系统登录后,需要缓存后端数据字典及行政区划及机构数据导致,由于该部分数据大约在1MB、1MB、2MB、2MB,总共在6MB左右,于是想到使用localStorage进行数据缓存时,localStorage是属于单线程,进行同步操作导致。于是查看相关资料,localStorage能缓存数据是5MB,没对该项进行仔细排查,于是排除是该问题导致。

通过多种方式排查后,发现还是不能有效找到导致加载缓慢原因,于是又重新定位到缓存部分,注释掉缓存逻辑代码,发布到生产环境,发现还是同样缓慢。于是就是排除缓存导致。有通过多种方式排查,还是不能找到异常原因。又再次把异常情况定位到缓存进行排查,还是注释掉缓存代码,并清除浏览器缓存,关闭浏览器,重新登录系统,并进入系统,发现能正常进入系统,经过多次测试正常,最终才确认是缓存后端数据导致。

2、问题深入分析

虽然localStorage能存储大小5MB,但是并比意味着数据存读取效率高,因为使用localStorage还涉及到数据序列化等,经过测试发现,存1MB数据到localStorage,大约需要10秒左右,由于localStorage又是单线程同步操作,并阻塞主线程,导致浏览器不能正常加载资源,因此导致初始进入系统,页面卡顿大概一分钟左右情况。

3、缓存解决方案

由于缓存数据量较大,因此经过分析,最终使用indexedDB解决。

4、localforage解决方案

查阅文档,发现indexedDB相关的API操作极为复杂,对于开发使用极为不便,因此想对indexedDB相关API进行封装。但是在查阅文档资料,发现localforage已对indexedDB进行高度封装,使用极其简易,因此选择localforage对数据进行缓存。部分核心代码如下:

//数据存取
      // 解决数据缓存卡顿问题
      const userStore = useUserStore();
      const indexedDB = localforage.createInstance({
        name: 'indexedDB',
        // 支持config所有配置
        // storeName: 'keyvaluepairs', // 仅接受字母,数字和下划线
      });
     // 接口数据请求
    getSysDictionary().then((res) => {
        if (res && Object.keys(res).length > 0) {
          // 数据缓存
          indexedDB.setItem(DB_DICT_DATA_KEY, res);
        }
      });

	// 数据读取
	indexedDB.getItem(DB_DICT_DATA_KEY).then((res) => {
        userStore.dictItems = res;
    });

由于indexedDB相关API数据读写都是异步操作,因此当需要进行同步访问时,需要使用关键字await进行操作。诺调用方法不能使用async关键字,即可能是通用方法封装或者涉及UI更新,必须同步返回,此事由于异步原因,不能很好处理,即便使用then或者promise也不便于处理,那么解决思路是,数据缓存到indexedDB时,同时缓存数据到浏览器页面,比如

useUserStore,此时能解决异步导致需要UI更新问题。

5.相关大数据学习demo地址:

https://github.com/carteryh/big-data

相关推荐
是梦终空9 小时前
JAVA毕业设计176—基于Java+Springboot+vue3的交通旅游订票管理系统(源代码+数据库)
java·spring boot·vue·毕业设计·课程设计·源代码·交通订票
天下无贼!13 小时前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
芊言芊语13 小时前
分布式缓存服务Redis版解析与配置方式
redis·分布式·缓存
攻城狮的梦14 小时前
redis集群模式连接
数据库·redis·缓存
无休居士18 小时前
【实践】应用访问Redis突然超时怎么处理?
数据库·redis·缓存
.Net Core 爱好者18 小时前
Redis实践之缓存:设置缓存过期策略
java·redis·缓存·c#·.net
M-bao18 小时前
缓存数据和数据库数据一致性问题
数据库·缓存
这个需求建议不做18 小时前
vue3打包配置 vite、router、nginx配置
前端·nginx·vue
QGC二次开发18 小时前
Vue3 : Pinia的性质与作用
前端·javascript·vue.js·typescript·前端框架·vue
AntDreamer19 小时前
在实际开发中,如何根据项目需求调整 RecyclerView 的缓存策略?
android·java·缓存·面试·性能优化·kotlin