Skip to content

Commit 1243797

Browse files
committed
Adding initial SSR fixes
1 parent ca47e6e commit 1243797

File tree

9 files changed

+8307
-9
lines changed

9 files changed

+8307
-9
lines changed

composer.lock

Lines changed: 8220 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/js/composables/useAppearance.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,50 @@ import { onMounted, ref } from 'vue';
33
type Appearance = 'light' | 'dark' | 'system';
44

55
export function updateTheme(value: Appearance) {
6+
if (typeof window === 'undefined') {
7+
return;
8+
}
9+
610
if (value === 'system') {
7-
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
11+
const mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
12+
const systemTheme = mediaQueryList.matches ? 'dark' : 'light';
813
document.documentElement.classList.toggle('dark', systemTheme === 'dark');
914
} else {
1015
document.documentElement.classList.toggle('dark', value === 'dark');
1116
}
1217
}
1318

14-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
19+
const mediaQuery = () => {
20+
if (typeof window === 'undefined') {
21+
return null;
22+
}
23+
24+
return window.matchMedia('(prefers-color-scheme: dark)');
25+
};
26+
27+
const getStoredAppearance = () => {
28+
if (typeof window === 'undefined') {
29+
return null;
30+
}
31+
return localStorage.getItem('appearance') as Appearance | null;
32+
};
1533

1634
const handleSystemThemeChange = () => {
17-
const currentAppearance = localStorage.getItem('appearance') as Appearance | null;
35+
const currentAppearance = getStoredAppearance();
1836
updateTheme(currentAppearance || 'system');
1937
};
2038

2139
export function initializeTheme() {
40+
if (typeof window === 'undefined') {
41+
return;
42+
}
43+
2244
// Initialize theme from saved preference or default to system...
23-
const savedAppearance = localStorage.getItem('appearance') as Appearance | null;
45+
const savedAppearance = getStoredAppearance();
2446
updateTheme(savedAppearance || 'system');
2547

2648
// Set up system theme change listener...
27-
mediaQuery.addEventListener('change', handleSystemThemeChange);
49+
mediaQuery()?.addEventListener('change', handleSystemThemeChange);
2850
}
2951

3052
export function useAppearance() {
@@ -42,8 +64,10 @@ export function useAppearance() {
4264

4365
function updateAppearance(value: Appearance) {
4466
appearance.value = value;
45-
localStorage.setItem('appearance', value);
46-
updateTheme(value);
67+
if (typeof window !== 'undefined') {
68+
localStorage.setItem('appearance', value);
69+
updateTheme(value);
70+
}
4771
}
4872

4973
return {

resources/js/layouts/settings/Layout.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const sidebarNavItems: NavItem[] = [
2020
},
2121
];
2222
23-
const currentPath = window.location.pathname;
23+
// For SSR, we can't access the window location
24+
const currentPath = (typeof window === 'undefined') ? '' : window.location.pathname;
2425
</script>
2526

2627
<template>

resources/js/ssr.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { createInertiaApp } from '@inertiajs/vue3'
2+
import createServer from '@inertiajs/vue3/server'
3+
import { renderToString } from '@vue/server-renderer'
4+
import { createSSRApp, h } from 'vue'
5+
import { type RouteName, route } from 'ziggy-js'
6+
7+
const appName = import.meta.env.VITE_APP_NAME || 'Laravel'
8+
9+
createServer(page =>
10+
createInertiaApp({
11+
page,
12+
render: renderToString,
13+
title: (title) => `${title} - ${appName}`,
14+
resolve: name => {
15+
const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
16+
return pages[`./Pages/${name}.vue`]
17+
},
18+
setup({ App, props, plugin }) {
19+
// Set up global route function for SSR
20+
// @ts-expect-error - Ziggy types
21+
global.route = <T extends RouteName>(name: T, params?: any, absolute?: boolean) =>
22+
route(name, params, absolute, {
23+
// @ts-expect-error - Ziggy types
24+
...page.props.ziggy,
25+
// @ts-expect-error - Ziggy types
26+
location: new URL(page.props.ziggy.location),
27+
})
28+
29+
const app = createSSRApp({
30+
render: () => h(App, props),
31+
})
32+
33+
app.use(plugin)
34+
35+
return app
36+
},
37+
}),
38+
)

resources/js/types/globals.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { route as routeFn } from "ziggy-js";
2+
3+
declare global {
4+
const route: typeof routeFn;
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { PageProps } from '@inertiajs/core';
22
import type { LucideIcon } from 'lucide-vue-next';
3+
import type { Config } from "ziggy-js";
34

45
export interface Auth {
56
user: User;
@@ -21,6 +22,7 @@ export interface SharedData extends PageProps {
2122
name: string;
2223
quote: { message: string; author: string };
2324
auth: Auth;
25+
ziggy: Config & { location: string };
2426
}
2527

2628
export interface User {

tsconfig.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,10 @@
119119
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
120120
"skipLibCheck": true /* Skip type checking all .d.ts files. */
121121
},
122-
"include": ["resources/js/**/*.ts", "resources/js/**/*.d.ts", "resources/js/**/*.tsx", "resources/js/**/*.vue"]
122+
"include": [
123+
"resources/js/**/*.ts",
124+
"resources/js/**/*.d.ts",
125+
"resources/js/**/*.tsx",
126+
"resources/js/**/*.vue"
127+
]
123128
}

vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import autoprefixer from 'autoprefixer';
33
import laravel from 'laravel-vite-plugin';
44
import path from 'path';
55
import tailwindcss from 'tailwindcss';
6+
import { resolve } from 'node:path';
67
import { defineConfig } from 'vite';
78

89
export default defineConfig({
910
plugins: [
1011
laravel({
1112
input: ['resources/js/app.ts'],
13+
ssr: 'resources/js/ssr.tsx',
1214
refresh: true,
1315
}),
1416
vue({
@@ -23,6 +25,7 @@ export default defineConfig({
2325
resolve: {
2426
alias: {
2527
'@': path.resolve(__dirname, './resources/js'),
28+
'ziggy-js': resolve(__dirname, 'vendor/tightenco/ziggy'),
2629
},
2730
},
2831
css: {

0 commit comments

Comments
 (0)