报错:Uncaught TypeError: Cannot read properties of undefined (reading ‘_s‘)
场景描述:项目进行依赖包更新后,本地可以正常运行访问使用,但是经过打包部署到线上后,显示一直在加载中,并且控制台报错。
排查复述(可跳过,个人纪录):
- 本项目是通过 vue-element-plus-admin 开源项目进行二次开发的,本次更新也是将 vue-element-plus-admin 的更新同步到我的项目中。
- 第一次排查:最初一点头绪都没有,并且本次更新内容比较多,所以先开始一点一点对比文件,看看是不是出现漏更,错更了,结果未发现问题。
- 这时我提交了issue,作者回复我开启souremap功能排查。
- 第二次排查:查看控制台报错定位是在,pinia.mjs 文件中,并且我这次也更新了pinia依赖包,就将 pinia 版本恢复到了原始版本,测试无果。
- 我又将这个开源项目试着打包部署看能不能访问,结果可以正常访问。
- 第三次排查:因为本地更新的功能版本比较多,很难定位问题,所以我开始一点一点功能的更新部署,最终发现是在更新vite版本时出现的问题,将vite3升级到vite4后就会报错。
- 第四次排查:找到一点线索:https://github.com/vuejs/pinia/discussions/1708?sort=top
发现每次报错都发生在请求接口的时候
将登录页面的所有接口请求注释了后,报错文件就会发生更改
随后我将每次报错文件中的报错定位都更改后,成功访问 - 第五次排查:但是这时所有请求都被注释了,但在其中有两个文件比较特殊,不是因为请求报错,在 store/auth.ts,和config/axios/service.ts 文件中是因为调用了 store 报错
- 最后我将所有请求打开,仅仅将store/auth.ts,和config/axios/service.ts 文件中调用 store的地方注释,测试打包部署,成功访问。
最终结果:
-
vite3中可以在一个store文件中方法外面调用另一个文件的store,但是vite4在打包后不支持
开始我使用调用的方式,这种方式在vite4中打包后访问会报错
import { useAppStore } from '@/store/modules/app' const appStore = useAppStore() // vite4会报错 export const useAuthStore = defineStore('auth', { state: (): AuthState => { return { user: {}, isUser: false } }, getters: { getUser(): UserState { return this.user }, getIsUser(): boolean { return this.isUser } }, actions: { login(formData) { const res = await loginApi(formData) if (res) { wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`) } return res } } }
可以改为
import { useAppStore } from '@/store/modules/app' export const useAuthStore = defineStore('auth', { state: (): AuthState => { return { user: {}, isUser: false } }, getters: { getUser(): UserState { return this.user }, getIsUser(): boolean { return this.isUser } }, actions: { login(formData) { const res = await loginApi(formData) if (res) { const appStore = useAppStore() // 改为在方法中调用, vite支持 wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`) } return res } } }
-
在创建axios实例文件中,同理
最开始的代码:
import { useAppStore } from '@/store/modules/app' const appStore = useAppStore() // vite4会报错 // 创建axios实例 const service: AxiosInstance = axios.create({ baseURL: '/api', headers: {} // 请求头信息 }) // request拦截器 service.interceptors.request.use( (config: InternalAxiosRequestConfig) => { const token = wsCache.get(appStore.getToken) if (token !== '') { ;(config.headers as any)['Authorization'] = token } if ( config.method === 'post' && (config.headers as any)['Content-Type'] === 'application/x-www-form-urlencoded' ) { config.data = qs.stringify(config.data) } if (config.method === 'get' && config.params) { let url = config.url as string url += '?' const keys = Object.keys(config.params) for (const key of keys) { if (config.params[key] !== void 0 && config.params[key] !== null) { url += `${key}=${encodeURIComponent(config.params[key])}&` } } url = url.substring(0, url.length - 1) config.params = {} config.url = url } return config }, (error: AxiosError) => { Promise.reject(error) } )
改为:
import { useAppStore } from '@/store/modules/app' // 创建axios实例 const service: AxiosInstance = axios.create({ baseURL: '/api', headers: {} // 请求头信息 }) // request拦截器 service.interceptors.request.use( (config: InternalAxiosRequestConfig) => { const appStore = useAppStore() // vite支持 const token = wsCache.get(appStore.getToken) if (token !== '') { ;(config.headers as any)['Authorization'] = token } if ( config.method === 'post' && (config.headers as any)['Content-Type'] === 'application/x-www-form-urlencoded' ) { config.data = qs.stringify(config.data) } if (config.method === 'get' && config.params) { let url = config.url as string url += '?' const keys = Object.keys(config.params) for (const key of keys) { if (config.params[key] !== void 0 && config.params[key] !== null) { url += `${key}=${encodeURIComponent(config.params[key])}&` } } url = url.substring(0, url.length - 1) config.params = {} config.url = url } return config }, (error: AxiosError) => { Promise.reject(error) } )