Reputation: 41
I want to include the following npm package in my component: tiny-slider-react.
However, while it works fine in Gatsby Develop, Gatsby Build fails with the following message:
error Building static HTML failed
See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html
3 | "use strict";
4 |
> 5 | if(!("remove" in Element.prototype)){
| ^
6 | Element.prototype.remove = function(){
7 | if(this.parentNode) {
8 | this.parentNode.removeChild(this);
WebpackError: ReferenceError: Element is not defined
- childNode.remove.js:5
[lib]/[ventura-slider]/src/helpers/childNode.remove.js:5:1
- childNode.remove.js:12 Object../node_modules/ventura-slider/src/helpers/childNode.remove.js
[lib]/[ventura-slider]/src/helpers/childNode.remove.js:12:2
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- tiny-slider.module.js:1 Module../node_modules/ventura-slider/src/tiny-slider.module.js
[lib]/[ventura-slider]/src/tiny-slider.module.js:1:1
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- Carousel.js:19 Object../node_modules/tiny-slider-react/build/Carousel.js
[lib]/[tiny-slider-react]/build/Carousel.js:19:19
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- index.js:7 Object../node_modules/tiny-slider-react/build/index.js
[lib]/[tiny-slider-react]/build/index.js:7:17
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- sync-requires.js:12 Object../.cache/sync-requires.js
lib/.cache/sync-requires.js:12:57
- bootstrap:19 __webpack_require__
lib/webpack/bootstrap:19:1
- static-entry.js:9 Module../.cache/static-entry.js
lib/.cache/static-entry.js:9:22
Commenting out this import and its’ React component fixes the issue.
Slideview.js
import React from 'react';
import TinySlider from "tiny-slider-react";
...
class SlideView extends React.Component{
render(){
return(
<TinySlider settings={settings}>
...
</TinySlider>
);
}
}
Expected: Slider works in production just like develop. Actual results: Breaks on build
Upvotes: 0
Views: 3253
Reputation: 41
Turns out I had to had the following lines to gatsby-node.js
gatsby-node.js
// /**
// * Implement Gatsby's Node APIs in this file.
// *
// * See: https://www.gatsbyjs.org/docs/node-apis/
// */
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /tiny-slider-react/,
use: loaders.null(),
},
],
},
})
}
}
It's at the bottom of this doc page. https://www.gatsbyjs.org/docs/debugging-html-builds/
Thanks Phillip for your help
Upvotes: 2
Reputation: 6253
During development, React components are only run in the browser. When building, Gatsby renders these components on the server - and in that context Element
(and stuff like window
and document
) is not defined.
I have no solution to your specific use-case, but when you want to do DOM-related manipulations, it should be done in componentDidMount
, which will only run in the browser.
My ideas for solving your issue:
Somehow only import and use the component in a parent componentDidMount
. This is IMO very fragile, and not the correct way
Fork the package and patch it, so the code that manipulates the Element
prototype is only run on browser. Eventually make a PR
EDIT:
I did some searching an came across this (somewhat) similar issue and solution: https://github.com/gatsbyjs/gatsby/issues/309#issuecomment-373359887.
// index.js
import React from "react";
import Link from "gatsby-link";
// import "uikit/dist/js/uikit";
// Third party JS access `window` without
// `typeof window !== "undefined"` check
class Template extends React.Component {
componentDidMount() {
import("uikit/dist/js/uikit")
.then((uikit) => {
this.uikit = uikit;
})
.catch((error) => console.error(error));
}
render() {
// ...
}
}
// ...
In essence, what you do is import the component in the componentDidMount
lifecycle hook, bind it to this.<MyComponent>
, and then use it in the render function:
render() {
const MyComponent = this.MyComponent;
return <MyComponent />;
}
Please note I have not tried this myself, but I don't see how this should not work. Do your own testing ;)
Upvotes: 1