I am using
I am trying to achieve the following:
I want to use ssr and have a vue component that uses the SplideJS - vue package. This package shouldn't load with ssr, since it dynamically adapts to screensizes etc. I just want it to skip loading in ssr and beeing hydrated only clientside.
My attempts:
"ignoring it in the vite.config.mjs
via "external" and "isCustomElement"
import {defineConfig} from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import {fileURLToPath, URL} from 'url';
import vuetify from "vite-plugin-vuetify";
export default defineConfig({
plugins: [
laravel({
input: ['resources/js/main.js'],
ssr: 'resources/js/ssr.js',
refresh: true,
}),
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.includes('Splide'),
}
},
}),
vuetify({
autoImport: true,
}),
],
ssr:
{
noExternal: ['@inertiajs/vue3/server'],
external: ['@splidejs/vue-splide'],
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./resources/js', import.meta.url)),
},
resolve: {
dedupe: [
'vue'
]
},
},
});
My main.js file
import { createApp, h } from "vue";
import { createInertiaApp, Link, Head } from "@inertiajs/vue3";
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
import { createPinia } from 'pinia';
import piniaPluginPersistedState from "pinia-plugin-persistedstate";
import '../css/app.css';
import VueSplide from '@splidejs/vue-splide';
import '@splidejs/splide/css';
const appName = "SSR Test";
const pinia = createPinia();
pinia.use(piniaPluginPersistedState);
createInertiaApp({
title: (title) => `${title} | ${appName}`,
resolve: (name) =>
resolvePageComponent(
`./Pages/${name}.vue`,
import.meta.glob('./Pages/**/*.vue')
),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue)
.use(pinia)
.use(VueSplide)
.component("Link", Link)
.component("Head", Head)
.mount(el);
},
progress: {
color: '#000000',
},
});
My ssr.js
import {createInertiaApp, Head, Link} from '@inertiajs/vue3';
import createServer from '@inertiajs/vue3/server'
import { renderToString } from '@vue/server-renderer';
import { createSSRApp, h } from 'vue';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createPinia } from 'pinia';
import { ZiggyVue } from 'ziggy-js';
const pinia = createPinia();
createServer((page) =>
createInertiaApp({
page,
render: renderToString,
title: (title) => `testtitle`,
resolve: (name) =>
resolvePageComponent(
`./Pages/${name}.vue`,
import.meta.glob('./Pages/**/*.vue'),
),
setup({ App, props, plugin }) {
return createSSRApp({
render: () => h(App, props),
})
.use(plugin)
.use(pinia)
.use(ZiggyVue, {
...page.props.ziggy,
location: new URL(page.props.ziggy.location),
})
.component("Link", Link)
.component("Head", Head);
},
}),
);
In my component I tried:
<template>
<div v-if="isClient">
<component :is="splideComponent" :options="options" aria-label="Unser Kundenservice"
>
<SplideSlide>
Slide 1
</SplideSlide>
<SplideSlide>
Slide 2
</SplideSlide>
<SplideSlide>
Slide 3
</SplideSlide>
</component>
</div>
</template>
<script setup>
import ContentBaseWhite from '@/Shared/Components/c-content-base-white.vue';
import {onMounted, ref} from "vue";
// Splide options
// only true in client
const isClient = ref(false);
// dynamic component
const splideComponent = ref(null);
// after dom is mounted, import splide component
onMounted(() => {
isClient.value = true;
import('@splidejs/vue-splide').then(module => {
splideComponent.value = module.Splide;
});
});
const options = ref({
options ...
});
When I start the inertia-ssr server via php artisan inertia:start-ssr
no error is received except in my firefox console:
[Vue warn]: Vue received a Component that was made a reactive object. This can lead to unnecessary performance overhead and should be avoided by marking the component with `markRaw` or using `shallowRef` instead of `ref`.
Component that was made reactive:
Object { name: "Splide", emits: (27) […], components: {…}, props: {…}, setup: setup(props, context), render: _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options)
}
at <CCustomerService>
at <BasicStoreLayout>
I am building via "build": "vite build && vite build --ssr".
Everything works fine without ssr. Right now it is sliding too, but isn't responsive at all + the error is confusing me. I copied a lot of code from a fresh laravel project but unfortunately there's not a lot of docu about "disable packages for ssr"
Any ideas what's the correct way to make this work?
Solved it via:
<div v-if="isClient" class="splide1">
<component :is="splideComponent" :options="options"
>
<component :is="splideSlideComponent">
Slide content..
</component>
<component :is="splideSlideComponent">
Slide content..
</component>
</div>
</template>
<script setup>
import {onMounted, ref, shallowRef} from "vue";
const isClient = ref(false);
const splideComponent = shallowRef(null);
const splideSlideComponent = shallowRef(null);
onMounted(async () => {
if (typeof window !== 'undefined') {
const { Splide, SplideSlide } = await import('@splidejs/vue-splide'); // Beide Komponenten importieren
splideComponent.value = Splide;
splideSlideComponent.value = SplideSlide;
isClient.value = true;
}
});
const options = ref({
perPage: 1,
});
</script>