Open midlantica opened 7 years ago
This is because there is no document
during server side rendering. You can use
Thank you! 😭
Nice! 😭
Ideally vue-carousel
itself would fix this. Vue components should be loadable with SSR by default.
You can simply fix this issue using config with SSR setup as @matthew-dean said.
create plugins/vue-carousel.js
:
import Vue from 'vue'
import VueCarousel from 'vue-carousel'
Vue.use(VueCarousel)
in nuxt.config.js
:
plugins: [{ src: '~plugins/vue-carousel', ssr: false }]
Then it's ready to use!! 🍙
How would I achieve this if I am not using nuxt and using the Hackernews demo ? I have tried using it in the app.js and I get the document error. If I use it anywhere else(entry-client.js). It fails saying content on server does not match the one on client, bails hydration and component is invisible now.
@mayognaise @ckpiggy thanks for the solution it worked. But I want to preload my carousel before sending to the client side, would u please help me with this?
You can put a v-if on the carousel make the variable true on mounted.
For ex
<template>
<div v-if="showCarousel">
<carousel
ref="mycarousel"
>
<slide v-for="some of something">
</carousel>
</div>
</template>
<script>
export default {
import { Carousel, Slide } from 'vue-carousel';
data() {
return {
showCarousel : false
}
}
mounted() {
// Vue.use(VueCarousel);
this.showCarousel = true;
},
}
</script>
Honestly, these "solutions" are not good. This is ridiculous. If you use SSR, you do it for a reason! You want all your content to be available for bots, crawlers etc. Any Vue.js component or library should be aware of that and prevent accessing window or document directly without checking for the environment first!
This IS a HUGE BUG and it should be fixed.
This works for me
Import:
import Carousel from 'vue-carousel/src/Carousel.vue'
import Slide from 'vue-carousel/src/Slide.vue'
Components:
components: {
Carousel,
Slide,
},
Template (pug)
carousel
slide(v-for='image in images')
img(:src='image')
For it to work seamlessly on DEVELOPMENT MODE
and PRODUCTION MODE
improving on
@mayognaise
and@SarasArya
create plugins/vue-carousel.js:
import Vue from 'vue'
import VueCarousel from 'vue-carousel'
Vue.use(VueCarousel)
in nuxt.config.js:
plugins: [{ src: '~plugins/vue-carousel', ssr: false }]
in your component
<template>
<div v-if="showCarousel">
<carousel
ref="mycarousel"
>
<slide v-for="some of something">
</carousel>
</div>
</template>
<script>
export default {
import { Carousel, Slide } from 'vue-carousel';
data() {
return {
showCarousel : false
}
}
mounted() {
// Vue.use(VueCarousel);
this.showCarousel = true;
},
}
</script>
This will enable it to work seamlessly on both production
and development
mode
No update?
@terryds no PR has been opened addressing full SSR support yet, is the above workaround not working for you?
@quinnlangille it's working without SSR
@kingflamez this solution is not working with latest Nuxt, it throws an error like:
ReferenceError: window is not defined
I used both <no-ssr>
and nuxt.config.js
improvements, no luck.
any solution for this problem
Hey @heshamelmasry77, since we can't seem to have a consistent success or failure with this issue I'm starting to believe it's a nuxt side issue rather than the carousel. I'll leave this chat open as discussion, but since we have documented successful implementations above I don't think anyone is actively pursuing another option
I'm using nuxt 1.4.2
and webpack 3.12.0
.
I tried both with the "local" import inside the component, or using global plugin.
I have no problem at all using the <carousel>
inside a <no-ssr>
tag up to version 0.11.0. Upgrading vue-carousel to version 0.12.0 or above, the error starts to pop out:
at Object.<anonymous> (/project_dir/node_modules/vue-carousel/dist/vue-carousel.min.js:6:204)```
any solution for this problem
The only solution for now is to use no-ssr
properly :)
<no-ssr placeholder="Loading...">
<IndexCarousel />
</no-ssr>
It turned out, that no-ssr
can have only one child. Now everything works fine.
this works too: https://gist.github.com/podlebar/340c9e7731b319d838eba083bb91a8ba
mix of dynamic import and mounted hook...
For anyone else facing this issue - the solution by @podlebar above was the only one that worked for me!
I can confirm the @podlebar solution is working with Nuxt@2.4.5 and vue-carousel@0.17.0, but I still see an error on server side:
ERROR [Vue warn]: Failed to resolve async component: () => Promise.resolve(/! import() /).then(__webpack_require__.t.bind(null, /! vue-carousel / "vue-carousel", 7)).then(m => m.Carousel).catch() Reason: ReferenceError: window is not defined
This could be because I was using nuxt dev mode, anyway, to prevent the server from even trying to resolve the import Promise, I modified the arrow functions returning component like this:
this modification generates no errors during server side rendering, and also prevents to hide import errors on the client side
components: {
Carousel: () => process.browser ? import('vue-carousel').then(m => m.Carousel) : null,
Slide: () => process.browser ? import('vue-carousel').then(m => m.Slide) : null
}
components: { Carousel: () => process.browser ? import('vue-carousel').then(m => m.Carousel) : null, Slide: () => process.browser ? import('vue-carousel').then(m => m.Slide) : null }
Please note that the solution above with delayed import, for Nuxt is required only when you don't want to make Carousel and Slide components available globally.
Otherwise using a Nuxt plugin (loaded with option ssr: true
-or mode: 'client'
or again ending the file name with client.js
for newer Nuxt versions) is all that you have to do, because you don't need to import Carousel and Slide to make them available to your pages and components.
Tested with Nuxt 2.4.5, vue-carousel 0.17.0, instantiating Carousel and Slide components only inside a <no-ssr>
element
// plugins/vue-carousel.client.js
import Vue from 'vue'
import VueCarousel from 'vue-carousel'
export default () => {
Vue.use(VueCarousel)
}
// nuxt.config.js
export default {
// ...
plugins: [
{ '~/plugins/vue-carousel.client.js', ssr: false }
]
// ...
}
// pages/show-me-the-carousel.vue
// Since <template> and <no-ssr> strictly require one root element, I'd usually prefer
// using divs instead of components or custom tags as the only direct child to them
// to prevent unwanted side effects
// (For example, <template> may output more than one root element so you should
// not use a <template> as a direct child for <no-ssr>
<template>
<div>
<no-ssr placeholder="A beautiful slider will be here after client-side hydration">
<div>
<carousel>
<slide v-for="(slide, index) in maBeautifulSlides">
<div class="ma-slide"> ... </div>
</slide>
</carousel>
</div>
</no-ssr>
</div>
</template>
<script>
export default {
data () {
maBeautifulSlides: [
// ...
]
}
}
</script>
With this you can start using <carousel />
and <slide />
components in your pages/components without importing anything, but strictly between <no-ssr></no-ssr>
tags otherwise you will get errors again.
I could solve it by using import { Carousel, Slide } from 'vue-carousel/src/index'
- maybe this helps others, too. Reason seems to be that it tries to inject styles at the wrong time when using the default minified version
@sebastianrothbucher this solved it for me too. On closer inspection of the webpack generated dist/vue-carousel.min.js it was referencing window early on in the code - and from searching around - this is a webpack behaviour? Anyhow referencing the src, seems to avoid the webpack dilemma and works nicely for SSR and client :)
Same issue when building my gridsome site. Solution from @sebastianrothbucher does not work there
There will be generated class VueCarousel-inner if you try to check the source then if you observed the element style of flex-basis is 0 and visibility hidden you can change that to example flex-basis: 425px;visibility: visible!important; through javascript although this not ssr anymore but still working and this works for me.
The solution by user @jorgvm for this issue is what got it to render for me.
Hey Fellas. Do we have any updates regarding SSR support and is the plugin going to be updated in general? I can see a lot of PRs opened but no new version since Apr 2019.
there's nothing new yet but you can try the solution i made. just read my comment above
@vokz vue-carousel works in general. Problem is SSR. Although you've suggested a good and resourceful solution TBH. Following the title itself and the feature request, I'm referring to the ability to render data so that bots from search engines can read them. After all, that's what Nuxt.js and SSR is for.
I found another issue while using this component with Nuxt.js, that it looks like to add some kind of Memory Leak to the application server. I tried loading it only on client side, jumping any load on server and everything related to SSR, but it kept increasing memory usage on server. And as soon I removed it from dependencies, the Memory Leak stoped totally.
I don't know if it was my implementation, I have done it pretty vanilla, with only basic features. So for a proper Nuxt module, it would be good to review it more deeply for this kind of issue. setInterval
and stuff like that that dont fit with Nuxt.js
I can help, wait for PR)
even using the Vue-cli for the build does not allow to automatically import styles during ssr. I see the only way out now is to extract the styles
or just import the src/*.vue
to nuxt directly
This https://github.com/SSENSE/vue-carousel/issues/81#issuecomment-363663139 worked for me and solved the issue of 'window' not defined
@arnabsen1729 You can try this package https://www.npmjs.com/package/@jambonn/vue-concise-carousel
Thanks @wesssel your solution works for me without using no-ssr. Anyone who still has an issue with SSR try his solution. It didn't look promising at a second, but it works.
Newbie. I had vue-carousel running great prior to an update, in nuxt I think. Now it simply won't work.
Running vue-carousel locally in component, Terminal: `[Vue warn]: Error in beforeCreate hook: "ReferenceError: document is not defined"
found in
--->