Hi guys, I'm working on a site which uses the mapbox-gl module, development mode works fine but it breaks in build stages. I am aware of the "(window/whatever) is undefined at build time" issue but I am unsure how to implement the solution. Almost all solutions I found revolve around Webpack configuration which is where I struggle in combination with Gatsby.
To be specific: Here seems to be the solution:
https://github.com/mapbox/mapbox-gl-js/issues/4359#issuecomment-288001933
but I don't know how to implement that in Gatsby. Do I have to put this in the Gatsby-node.js file? I have tried but without success. I'd be happy if someone could advise.
Here's my Gatsby-node.js:
`
const makeRequest = (graphql, request) =>
new Promise((resolve, reject) => {
// Query for nodes to use in creating pages.
resolve(
graphql(request).then(result => {
if (result.errors) {
reject(result.errors);
}
return result;
})
);
});
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage } = boundActionCreators;
const getPage = makeRequest(
graphql,
`
{
allStrapiReferenz {
edges {
node {
id
Headline
Ref_Category
}
}
},
allStrapiArbeitsgebiete{
edges{
node{
id
Arbeitsgebiet_Titel
}
}
}
}
`
).then(result => {
result.data.allStrapiReferenz.edges.forEach(({ node }) => {
createPage({
path: `/referenz/${slugify(node.Ref_Category)}/${slugify(node.Headline)}`,
component: path.resolve(`src/templates/referenz.js`),
context: {
id: node.id,
},
});
});
result.data.allStrapiArbeitsgebiete.edges.forEach(({ node }) => {
createPage({
path: `/arbeitsgebiete/${slugify(node.Arbeitsgebiet_Titel)}`,
component: path.resolve(`src/templates/arbeitsgebiete.js`),
context: {
id: node.id,
},
});
});
});
// Query for articles nodes to use in creating pages.
return getPage;
};`
I should add I have tried the steps here (under fixing 3rd party modules):
https://www.gatsbyjs.org/docs/debugging-html-builds/
but that also threw an error:
WebpackError: (0 , _reactMapboxGl2.default) is not a function
so I guess the solution is not to skip the module but to skip the uglification of the module ...
I had the same problem, was hard to debug and hard to solve.
End up with something like this on gatsby-node.js
exports.onCreateWebpackConfig = ({ stage, actions, getConfig }) => {
const config = getConfig();
let newConfig = {
...config,
module: {
...config.module,
noParse: /(mapbox-gl)\.js$/,
},
};
if (stage === 'build-html') {
newConfig = {
...newConfig,
module: {
...newConfig.module,
rules: [
...newConfig.module.rules,
{
test: /(mapbox-gl)\.js$/,
loader: 'null-loader',
},
],
},
};
}
actions.replaceWebpackConfig(newConfig);
};
@porfirioribeiro Thank you and sorry for the late reply. Unfortunately it did not work. Do I have to adjust anything in the Webpack config you pasted?
Hey @dwehrmann. I hope you found a solution to this. I was able to get mine working with some logic inside the component to create a mock Map instance when it's in build. I'm also using react-mapbox-gl.
let mapboxgl
let ReactMapboxGl = {}
if (typeof window !== `undefined`) {
mapboxgl = require('mapbox-gl')
ReactMapboxGl = require('react-mapbox-gl')
} else {
ReactMapboxGl.Map = () => {
return class Mock extends React.Component {
constructor() {
super()
}
render() {
return <div />
}
}
}
}
const Map = ReactMapboxGl.Map({
accessToken: '[your-token-here]',
})
class DirectoryMap extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div className="directory-map">
<Map
ref={e => {
this.map = e
}}
zoom={[11]}
speed={[0.6]}
>
</Map>
</div>
)
}
}
Hi @stemmlerjs – thank you! Similar to your solution, I was able to solve this by using class extends like that:
class RefMap extends React.Component {
createMap() {
const iconSize = 1
const map = new mapboxgl.Map({
center: this.props.center,
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
trackResize: 'true',
zoom: this.props.zoom,
pitch: 50,
detectRetina: 'true'
})
var el = document.createElement('div');
el.className = 'marker';
el.style.backgroundImage = 'url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTIwMCIgaGVpZ2h0PSIxMjAwIiB2aWV3Qm94PSIwIDAgMTIwMCAxMjAwIj48Zz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZmZmZmZmIj48L3JlY3Q+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjAwIDYwMCkgc2NhbGUoMC42OSAwLjY5KSByb3RhdGUoMCkgdHJhbnNsYXRlKC02MDAgLTYwMCkiIHN0eWxlPSJmaWxsOiNmNDdmMjQ7Ij48c3ZnIGZpbGw9IiNmNDdmMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAgMTAwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJNNTAsMjVjNi44OTYsMCwxMi41LDUuNjA0LDEyLjUsMTIuNVM1Ni44OTYsNTAsNTAsNTBzLTEyLjUtNS42MDQtMTIuNS0xMi41UzQzLjEwNCwyNSw1MCwyNXogTTUwLDAgIEMyOS4xNjcsMCwxMi41LDE2LjY2NywxMi41LDM3LjVTMjkuMTY3LDc1LDUwLDEwMGMyMC44MzMtMjUsMzcuNS00MS42NjcsMzcuNS02Mi41UzcwLjgzMywwLDUwLDB6Ij48L3BhdGg+PC9zdmc+PC9nPjwvZz48L3N2Zz4=);)'
map.on('load', () => {
new mapboxgl.Marker(el)
.setLngLat(this.props.center)
.addTo(map);
(map) => { map.resize() }
})
}
componentDidMount() {
mapboxgl.accessToken = '[TOKEN]'
this.createMap()
}
render() {
return (
<div id={'map'} style={{ width: '100%', height: '100%' }} />
)
}
And in my gatsby-node.js:
exports.modifyWebpackConfig = ({ config, stage }) => {
if (stage === "build-html") {
config.loader("null",
{
test: /isotope\-|fizzy\-ui\-utils|desandro\-|masonry|outlayer|get\-size|doc\-ready|eventie|eventemitter|react-mapbox-gl|react-mapbox-gl|react-map-gl|(mapbox-gl)\.js$/,
loader: "null-loader",
},
);
}
};
note that I had to exclude isotope.js as well.
Things are working now, thank you everyone! Hopefully this thread will be useful for somebody else as well.
I know this issue is closed, but @porfirioribeiro's solution worked for me. Just pasted his code in gatsby-node.js
Thank you very much!
Most helpful comment
Hi @stemmlerjs – thank you! Similar to your solution, I was able to solve this by using class extends like that:
And in my gatsby-node.js:
note that I had to exclude isotope.js as well.
Things are working now, thank you everyone! Hopefully this thread will be useful for somebody else as well.