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

如何在Laravel/Inertia后端SSR模式下使用VueUse的createCookies(req)函数?

解决Laravel/Inertia SSR下VueUse useCookies失效问题

核心思路

SSR模式下useCookies无法直接访问请求上下文,需改用createCookies并区分服务端/客户端环境:

  • 服务端:通过Laravel传递的页面props获取初始主题值,同时利用SSR上下文的请求对象初始化createCookies
  • 客户端:直接初始化createCookies,与原useCookies用法一致

代码修改步骤

1. 更新Pinia主题Store(useThemes.ts)

import { createCookies } from '@vueuse/integrations/useCookies'
import { defineStore } from 'pinia'
import { ref, useSSRContext } from 'vue'
import { usePage } from '@inertiajs/vue3'

export type Theme = string

export const useThemes = defineStore('themes', () => {
    // 区分服务端/客户端初始化Cookies实例
    let cookies
    if (process.server) {
        // 服务端从SSR上下文获取请求对象
        const ssrContext = useSSRContext()
        cookies = createCookies({ req: ssrContext?.req })
    } else {
        // 客户端直接初始化
        cookies = createCookies()
    }

    // 获取Laravel传递的页面props
    const page = usePage()
    // 服务端用props初始值,客户端优先读Cookie,无则用默认值
    const initialTheme = process.server 
        ? page.props.value.themeCookie 
        : cookies.get('theme') || 'default'
    const theme = ref(initialTheme)

    /**
     * @field General themes
     */
    const generalThemes: Theme[] = ['Default', 'Light', 'Dark']

    /**
     * @field Light themes
     */
    const lightThemes: Theme[] = [
        'Cupcake', 'Corporate', 'Fantasy', 'Autumn', 'Winter',
        'Limonade', 'Garden', 'Retro', 'Cyberpunk', 'Valentine', 'Nord'
    ]

    /**
     * @field Dark themes
     */
    const darkThemes: Theme[] = ['Coffee', 'Aqua', 'Night', 'Sunset', 'Halloween', 'Business']

    /**
     * Set theme by string name
     * @param {string} themeName Theme to be set
     */
    function setTheme(themeName: string) {
        const capitalizedTheme = capitalize(themeName)
        if (
            themeName?.trim() &&
            (generalThemes.includes(capitalizedTheme) ||
                lightThemes.includes(capitalizedTheme) ||
                darkThemes.includes(capitalizedTheme))
        ) {
            theme.value = themeName
            // 仅在客户端设置Cookie,避免服务端报错
            if (!process.server) {
                cookies.set('theme', theme.value)
            }
        }
    }

    /**
     * Capitalize a string's first letter
     * @param {string} value String to be capitalized
     */
    function capitalize(value: string): string {
        return value
            .split(' ')
            .map(word => word[0].toUpperCase() + word.substring(1))
            .join(' ')
    }

    /**
     * Initialize theme if not set
     */
    function initTheme() {
        setTheme(theme.value)
    }

    return { theme, initTheme, setTheme, generalThemes, lightThemes, darkThemes }
})

2. 全局共享Cookie数据(优化后端代码)

当前仅在home方法传递themeCookie,建议在HandleInertiaRequests中间件中全局共享,避免重复编写:

<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    protected $rootView = 'app';

    public function share(Request $request)
    {
        return array_merge(parent::share($request), [
            'themeCookie' => $request->cookie('theme') ?? 'default',
            'animatedCookie' => boolval($request->cookie('animated')) ?? true,
            // 其他全局共享数据...
        ]);
    }
}

3. 验证渲染一致性

服务端渲染时,页面直接使用themeCookie的值初始化主题,避免客户端 hydration 不匹配;客户端切换主题时,setTheme自动更新Cookie,下次刷新页面时Laravel会读取最新值传递给前端,保证SSR与客户端状态一致。

关键说明

  • process.server是Vite/Node环境变量,用于区分服务端/客户端执行逻辑
  • 服务端通过useSSRContext()获取Inertia SSR请求上下文,传递给createCookies
  • 客户端设置Cookie的逻辑仅在浏览器环境执行,避免服务端报错

内容的提问来源于stack exchange,提问作者Reza Hajianpour

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:54:51