You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vuexy模板(Vite+Vue3+Vuetify)添加SSR遇window/localStorage未定义问题

解决方案

1. 环境判断:隔离浏览器API调用

所有涉及localStorage、window的代码,必须先判断当前运行环境是否为浏览器,避免服务端执行时报错:

  • 直接在代码中添加判断:
    if (typeof window !== 'undefined') {
      // 仅在客户端执行浏览器相关操作
      const savedTheme = localStorage.getItem('app-theme')
      window.addEventListener('resize', handleResize)
    }
    
  • 封装工具函数复用,减少重复代码:
    // utils/browser-utils.js
    export const isClient = () => typeof window !== 'undefined'
    export const getStorageItem = (key) => isClient() ? localStorage.getItem(key) : null
    export const setStorageItem = (key, val) => isClient() && localStorage.setItem(key, val)
    
    在组件或状态管理中导入使用:
    import { getStorageItem } from '@/utils/browser-utils'
    const userPrefs = getStorageItem('user-preferences')
    

2. Pinia状态管理适配SSR

Pinia在SSR场景下每个请求需要独立实例,且禁止在store初始化阶段调用浏览器API:

  • 修改store逻辑,将依赖浏览器API的初始化逻辑移到actions中,在客户端生命周期钩子触发:
    // stores/app.js
    import { defineStore } from 'pinia'
    
    export const useAppStore = defineStore('app', {
      state: () => ({
        theme: 'light'
      }),
      actions: {
        initClientState() {
          if (typeof window !== 'undefined') {
            this.theme = localStorage.getItem('app-theme') || 'light'
          }
        }
      }
    })
    
  • 在组件的onMounted钩子中调用初始化方法(服务端不会执行该钩子):
    import { useAppStore } from '@/stores/app'
    import { onMounted } from 'vue'
    
    const appStore = useAppStore()
    onMounted(() => {
      appStore.initClientState()
    })
    

3. Vuetify主题配置调整

避免在Vuetify实例初始化阶段读取localStorage,改为客户端挂载后动态更新:

// main.js
import { createApp } from 'vue'
import { createVuetify } from 'vuetify'

// 基础主题配置(服务端渲染时使用默认值)
const vuetify = createVuetify({
  theme: {
    defaultTheme: 'light'
  }
})

const app = createApp(App)
app.use(vuetify)

// 客户端挂载后读取本地存储并更新主题
if (typeof window !== 'undefined') {
  const savedTheme = localStorage.getItem('app-theme')
  if (savedTheme) {
    vuetify.theme.global.name.value = savedTheme
  }
}

app.mount('#app')

4. 第三方插件/组件适配

如果项目中存在直接依赖window的插件(如Vuexy自带的主题插件),调整加载时机:

  • 动态导入插件,仅在客户端环境加载:
    // main.js 或插件注册文件
    if (typeof window !== 'undefined') {
      import('@/plugins/theme-plugin').then(module => {
        app.use(module.default)
      })
    }
    
  • 若插件源码可修改,直接在插件内部添加环境判断,包裹所有浏览器API调用逻辑。

5. Vite SSR配置优化

确保Vite正确区分客户端与服务端打包逻辑:

// vite.config.js
export default defineConfig({
  ssr: {
    noExternal: ['vuetify'] // 确保Vuetify被SSR兼容处理
  },
  build: {
    ssr: true,
    rollupOptions: {
      input: {
        server: './src/entry-server.js',
        client: './src/entry-client.js'
      }
    }
  }
})

内容的提问来源于stack exchange,提问作者tareq safia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:21:09