Update: Splide is now in Version 3 and (since the update) React Splide appears to work well with Gatsby (tested on V4) without any additional configuration. This article is only useful to those using an older version of React Splide.
If you have never come across SplideJS then I encourage you to check it out. It's a great plugin for building carousels and I think the documentation is brilliant. Check out SplideJS here.
Let me start by telling you about my painful afternoon...
Today, I have been working on a website for a client using Gatsby. Until today, everything has been going great! My task today was to develop a carousel component, so I turned to my favourite tool (Splide) and I noticed they have a React port. "Awesome" I thought, "This is going to be simple!".
Then I noticed an error in the Netlify logs.
14 | else
15 | root["Splide"] = factory();
> 16 | })(self, function() {
| ^
17 | return /******/ (() => { // webpackBootstrap
18 | /******/ "use strict";
19 | /******/ var __webpack_modules__ = ({
WebpackError: ReferenceError: self is not defined
This doesn't look good.
Debugging Gatsby HTML Builds
There's a great section in the Gatsby documentation about debugging HTML builds here. I consulted this and found the section on third-party modules. I have used this approach with other packages that expect the window
object during the HTML build, so I thought I would give this a go.
In gatsby-node.js
I added the following:
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
// With SSR enabled during development, we capture this
// in development and during production build.
if (stage === "build-html" || stage === "develop-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /@splidejs/,
use: loaders.null(),
},
],
},
})
}
}
Great 💥 let's run gatsby build
again...oh dear
Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant=130&args[]=undefined&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
We have a new error. A new error is good, it means progress! If we copy the error decoder URL into a new browser we can see that React returned the following error.
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
At first I was puzzled, but after a coffee it made sense. We have told webpack to replace React Splide with a dummy module. The loaders.null()
suggests that we're not going to return anything valuable - it's undefined
.
So the end result for my carousel component was this:
export const Testimonials = ({ data }) => {
if (typeof window === "undefined") {
return <p>Server Render</p>
}
return (
<Box mb={24}>
<Splide
options={{
perPage: 1,
perMove: 1,
arrows: false,
}}
>
{data.map(testimonial => {
return (
<SplideSlide key={testimonial.id}>
<Flex bgColor="blue.600">
<Box width="400px">
{/* To be replaced with Gatsby Image */}
<img src={testimonial.imageUrl} alt={testimonial.alt} />
</Box>
<Box py={12} px={12} display="flex" flex={1} color="white">
<PortableText blocks={testimonial._rawTestimonialText} />
</Box>
</Flex>
</SplideSlide>
)
})}
</Splide>
</Box>
)
}
This means that when the HTML build takes place, the component will return <p>Server Render</p>
rather than undefined
. If we run the code in the browser, window
is defined and we will see the Splide component.
Conclusion
I wrote this with the hope that it will help anyone else who comes across this problem. If you found it useful then let me know in the comments.
Thanks!
Top comments (17)
Awesome article! I wonder do you know what is the root cause of this? I am currently struggling with this error with an internal third party library which I can easily contribute to. Is something messed up with the build output of that third party library (maybe tweak the Webpack / Rollup config on the libraries side)?
Ah I think Gatsby does not work well with UMD library output. I've changed the third party library to use CommonJS and now I don't need any workarounds.
Here is my rollup config:
The libraries tsconfig.json:
and my build command:
tsc -p . && rollup -c
Sorry @brunnerlivio I missed your comment. That's a great find, I wasn't sure of the root cause myself but your insight is really useful. Thank you.
Worte an article shedding a light on this here:
dev.to/brunnerlivio/use-stencil-wi...
Hi Jamie, thank you so much for this article!
It's the only one that helped me get Splidejs (great tool) and Gatsby working on the site I was building.
Just one suggestion, with the new SSR Gatsby functionality set to true (and so active) now it's better to update the if statement inside the onCreateWebpackConfig to "if (stage === "build-html" || stage === "develop-html")" so that you don't receive any error during development phase (gatsby develop). At least I had to do it. Maybe you could update the article with this info, it could help someone else.
Thank you so much for your help
Sorry for the delayed response Marco! I've had some time away from this site for a bit as I've been busy with day job. Yeah absolutely I'll get this updated and thank you for sharing.
Hi Jamie, thanks for the tutorial!
But i follow the step above, and it seems the errors still appear.
Do you have any idea?
Oh that's not good (and slightly awkward 😬) which of the errors are you still getting? I'm presuming you mean:
Let me know. I'm happy to have a look if you want share the code with me, maybe DM me on Twitter(@jamiebradley234)?
Here's my code pastebin.com/m4cB3Rec
Btw, I can't send the dm to your Twitter.
Thanks, can you send me your twitter handler please and I'll try reaching out to you over Twitter. I've got some questions but I don't want to spam the thread 😂
Sure, twitter.com/difaananda40
Thanks for going through this with me on Twitter! For everyone else's reference the change was to update object in the rules array from:
to
I have updated the post accordingly!
Hi Jamie, I followed these steps and the build ran fine. But getting this error on the rendered HTML:
[SPLIDE] Track or list was not found.
j @ splide.esm.js:953
2react-dom.production.min.js:216 TypeError: Cannot read property 'length' of undefined
at Object.get length as length
at i.get (splide.esm.js:1838)
at Object.get edgeIndex as edgeIndex
at Object.handler (splide.esm.js:2755)
at splide.esm.js:139
at Array.forEach ()
at Object.emit (splide.esm.js:137)
at i.r.emit (splide.esm.js:1703)
at i.r.refresh (splide.esm.js:1772)
at m.value (Splide.js:208)
Hi, if you're still having issues I suggest you try reverting the changes made and importing node-self before your splider import.
The
self is not defined
error relates toself
not being implemented in NodeJs - the above fixes that issue and the result should be a fully working SSR rendered splider. (At least that is the case in my Gridsome project).Cheers!
Thanks @animald , appreciate the input!
Sorry for the delay Zubair, interesting as I've not seen this error before. I don't suppose this is related to Marco's comment regarding SSR during dev? I'm only asking with you saying that the build worked fine. I'm reading this as it worked during build phase but not dev phase. Thanks!
Thanks, I was looking exactly for a solution for that problem!