如何在Laravel/Inertia后端SSR模式下使用VueUse的createCookies(req)函数?
核心思路
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
相关产品推荐
相关产品推荐

