MST

星途 面试题库

面试题:Vue SSR场景下Vuex异步数据加载与缓存策略的设计与实践

在Vue服务端渲染(SSR)的项目中,结合Vuex实现异步数据加载与缓存策略面临哪些挑战?如何设计一个高效的方案,确保在服务端和客户端都能正确地处理异步数据加载和缓存,并且保证数据一致性?请详细说明设计思路、关键代码实现以及可能遇到的坑和解决方案。
49.4万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

面临的挑战

  1. 服务端和客户端状态不一致:由于服务端和客户端渲染的时机不同,可能导致初始状态不一致,进而影响异步数据的加载和缓存。
  2. 缓存管理:如何有效地管理缓存,避免缓存过期或数据更新不及时,特别是在高并发情况下。
  3. 数据预取:在服务端渲染时,需要在合适的时机预取数据,同时要考虑预取数据的性能开销。
  4. 内存管理:在服务端,过多的缓存数据可能导致内存占用过高,需要合理的内存回收策略。

设计思路

  1. 统一状态管理:使用Vuex作为状态管理工具,确保服务端和客户端共享相同的状态结构。
  2. 数据预取:在服务端渲染时,通过路由钩子或生命周期钩子预取数据,并将数据填充到Vuex store中。
  3. 缓存策略:为每个异步请求设置缓存标识和过期时间,根据缓存标识判断数据是否已缓存,根据过期时间决定是否重新获取数据。
  4. 状态同步:在客户端激活时,将服务端渲染填充的Vuex状态同步到客户端,避免重复获取数据。

关键代码实现

1. 服务端数据预取

// 在服务端路由钩子中预取数据
import { createRouter } from './router'
import { createStore } from './store'

export default async (context) => {
  const router = createRouter()
  const store = createStore()

  // 设置当前路由
  router.push(context.url)

  // 等待路由解析完成
  await router.isReady()

  // 获取匹配的路由组件
  const matchedComponents = router.currentRoute.value.matched

  // 预取数据
  const prefetchPromises = matchedComponents
  .filter(component => component.asyncData)
  .map(component => component.asyncData({ store, route: router.currentRoute.value }))

  // 等待所有预取数据的Promise完成
  await Promise.all(prefetchPromises)

  return { router, store }
}

2. 异步数据加载与缓存

// Vuex模块示例
const module = {
  namespaced: true,
  state: () => ({
    data: null,
    cacheTime: null,
    CACHE_EXPIRE_TIME: 60 * 1000 // 缓存过期时间1分钟
  }),
  mutations: {
    SET_DATA(state, data) {
      state.data = data
      state.cacheTime = new Date().getTime()
    }
  },
  actions: {
    async fetchData({ state, commit }) {
      if (state.data && new Date().getTime() - state.cacheTime < state.CACHE_EXPIRE_TIME) {
        return state.data
      }
      const response = await fetch('/api/data')
      const data = await response.json()
      commit('SET_DATA', data)
      return data
    }
  }
}

3. 客户端状态同步

// 在客户端入口文件中同步状态
import { createApp } from 'vue'
import { createStore } from './store'
import App from './App.vue'

const store = createStore()

// 将服务端渲染时填充的状态同步到客户端
if (window.__INITIAL_STATE__) {
  store.replaceState(window.__INITIAL_STATE__)
}

const app = createApp(App)
app.use(store)
app.mount('#app')

可能遇到的坑和解决方案

  1. 客户端激活时数据重复请求:解决方案是在客户端激活时,将服务端渲染填充的Vuex状态同步到客户端,如上述客户端状态同步代码所示。
  2. 缓存过期处理不当:需要严格按照设定的缓存过期时间来判断是否重新获取数据,并且在数据更新时及时更新缓存时间。
  3. 服务端内存占用过高:可以通过设置合理的缓存过期时间,定期清理缓存数据,或者采用LRU(最近最少使用)等缓存淘汰策略来管理内存。
  4. 跨域问题:在服务端预取数据时,可能会遇到跨域问题。可以通过在服务端设置代理或者使用CORS(跨域资源共享)来解决。