Closed sayjeyhi closed 5 years ago
Gatsby is a ssr(server side framework), meaning that all the build process is done in node. With that won't have access to certain apis, like canvas. And it generates that error. As a workaround you could probably use react- loadable, for instance, let me see if I can make a reproduction of both packages and report back, do you mind waiting a bit?
@jonniebigodes Yeah , thatswhy I used node-canvas , to bring canvas to SSR , but I could not make it to build the gatsby
static files..
Sure, thanks for your feedback 💯
Hi!
Sorry to hear you're running into an issue. To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.
If you're up for it, we'd very much appreciate if you could provide a minimal reproduction and we'll be able to take another look.
Thanks for using Gatsby! 💜
@LekoArts I translate the game and add it on a sandbox here : https://codesandbox.io/s/snakeandladders-ricvr
@jafar-rezaei i've cloned your codesandbox and it seems that i have a solution for you. Going to test out a couple of things and report back.
@jafar-rezaei i think i have a solution for your issue. Below are the steps i took to try and solve it.
Grabbed your codesandbox code.
Installed the dependencies.
Issued gatsby build && gatsby serve
and i was able to confirm your issue, the same message popped up.
Checked gatsby-node.js
modified it to the following:
exports.onCreateWebpackConfig = ({
stage,
rules,
loaders,
plugins,
actions,
}) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /canvas/,
use: loaders.null(),
},
],
},
})
}
};
With this small change once the build enters the build-html
stage, the package in question, namely canvas
will be "silenced" and returns a empty module. This is due to the fact that this package will try to use apis that are not in the node side like window
for instance. But will cause no loss in functionality as you can see below.
Issued gatsby build && gatsby serve
to create a production build and i'm presented with a error regarding redux, the way it's implemented it's not gatsby/ssr optimized.
With that in mind i changed the code inside src/store/index.js
to the following:
const windowGlobal = typeof window !== 'undefined' && window;
const devtools = process.env.NODE_ENV === 'development' && windowGlobal.devToolsExtension ? window.REDUX_DEVTOOLS_EXTENSION && window.REDUX_DEVTOOLS_EXTENSION() : f => f;
const store = createStore( rootReducer, compose( applyMiddleware(logger, sagaMiddleware), devtools ) ); sagaMiddleware.run(rootSaga) export default store;
This small change will check for both mode(development/production) and window and load the devtools accordingly.
- Issued `gatsby clean && gatsby build && gatsby serve`, to set a a clean slate on the build, issue a production build and emulate a production server and i'm presented with the following:
![canvas_build_1](https://user-images.githubusercontent.com/22988955/65082982-3d1f4e00-d99f-11e9-9b4c-8daa4d24f9cf.png)
- Opened up a new browser window to `http://localhost:9000` and started a new game and i'm presented with the following:
![canvas_build_2](https://user-images.githubusercontent.com/22988955/65083029-5cb67680-d99f-11e9-830f-c48a50fbab0b.png)
- Issued `gatsby clean && gatsby develop`, once again purge the folders associated to the build process(.cache and public) to generate a development build, just to check if the redux devtools as being loaded correctly.
- Opened up `http://localhost:8000` and started a new game and i'm presented with the following:
![canvas_build_3](https://user-images.githubusercontent.com/22988955/65083265-01d14f00-d9a0-11e9-8c91-f78a81de39fe.png)
The devtools are being loaded and also the package aswell.
Feel free to provide feedback so that we can close this issue or continue to work on it until we find a suitable solution.
Big thanks @jonniebigodes , the problem solved
@jafar-rezaei no need to thank. Glad that i was able to solve your issue.
@jafar-rezaei @jonniebigodes
The canvas package is meant to work both in the browser and on Node.js, with the use of separate files for each platform. In our package.json, we've added a line to tell bundlers to use the file browser.js
when building for browsers, and index.js
when running on Node.js.
I thought that WebPack would automatically pick up on this 🤔 are you using any configuration that would make that not work?
@LinusU i don't know how familiar you are with gatsby but all of the build is done on the node side of things, from my testing and based on the code @jafar-rezaei supplied the bundler/webpack configuration is the default that gatsby offers out of the box, with a small caveat and that is to ignore the canvas library during the build process, as outlined in these lines:
exports.onCreateWebpackConfig = ({
stage,
rules,
loaders,
plugins,
actions,
}) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /canvas/,
use: loaders.null(),
},
],
},
})
}
};
It could be that the property browser
you mentioned isn't being picked up by gatsby's webpack out of the box. I'm not knowledgeable of the webpack workflow of gatsby, but it could be that with some work and some changes this can work with gatsby. I'll ping the @gatsbyjs/core for some insight on this, on a personal level if the two, with some work can be better integrated i think that the community would benefit a bit more.
Thank for this. As a side note we also had this issue during gatsby develop
as well. When running gatsby develop the stage is develop-html
. So if you are getting this error during development you can always add this as an or conditional in the stage check in the above fix.
@larryg727 when this was written it was intended for production build with Gatsby, with that i ommited any configurations relevant to that. But nonetheless nice touch to include it and expand the response.
Thank for this. As a side note we also had this issue during
gatsby develop
as well. When running gatsby develop the stage isdevelop-html
. So if you are getting this error during development you can always add this as an or conditional in the stage check in the above fix.
@larryg727 you saved me a huge headache. Thank you
I have an eraser effect with canvas on my Gatsby application. On the home page users can erase the canvas to see the video underneath the canvas.
Everything works as normal on my local machine but when I serve the app, the canvas and video do not load initially. However, if I navigate to any page within the app and back to home page, the canvas and video load and work properly.
I am new to Gatsby, please how can I resolve this.
Please see below code:
const HomePage = () => {
let canvas = useRef(null)
const size = useWindowSize()
const { currentTheme } = useGlobalStateContext()
useEffect(() => {
let renderingElement = canvas.current
let drawingElement = renderingElement.cloneNode()
let drawingCtx = drawingElement.getContext("2d")
let renderingCtx = renderingElement.getContext("2d")
let lastX
let lastY
let moving = false
renderingCtx.globalCompositeOperation = "source-over"
renderingCtx.fillStyle = currentTheme === "dark" ? "#000000" : "#ffffff"
renderingCtx.fillRect(0, 0, size.width, size.height)
renderingElement.addEventListener("mouseover", e => {
moving = true
lastX = e.pageX - renderingElement.offsetLeft
lastY = e.pageY - renderingElement.offsetTop
})
renderingElement.addEventListener("mouseup", e => {
moving = false
lastX = e.pageX - renderingElement.offsetLeft
lastY = e.pageY - renderingElement.offsetTop
})
renderingElement.addEventListener("mousemove", e => {
if (moving) {
drawingCtx.globalCompositeOperation = "source-over"
renderingCtx.globalCompositeOperation = "destination-out"
let currentX = e.pageX - renderingElement.offsetLeft
let currentY = e.pageY - renderingElement.offsetTop
drawingCtx.lineJoin = "round"
drawingCtx.moveTo(lastX, lastY)
drawingCtx.lineTo(currentX, currentY)
drawingCtx.closePath()
drawingCtx.lineWidth = 120
drawingCtx.stroke()
lastX = currentX
lastY = currentY
renderingCtx.drawImage(drawingElement, 0, 0)
}
})
}, [currentTheme])
return (
<Container>
<Video>
<video
height="100%"
width="100%"
loop
autoPlay
muted
src={require("../assets/somevideo.mp4")}
/>
</Video>
<Canvas
width={size.width}
height={size.height}
ref={canvas}
/>
</Container>
)
}
i got the same error as @sayjeyhi and just like @larryg727 it happens during gatsby develop...
@jonniebigodes so your approach is to mute the canvas plugin, did i understand this correctly? with
actions.setWebpackConfig({
module: {
rules: [
{
test: /canvas/,
use: loaders.null(),
},
],
},
})
your are essentially doing the same as writing
actions.setWebpackConfig({
externals: ['canvas']
})
but with canvas muted, an error is thrown in the browser now.
i get a TypeError: Object(...) is not a function because this import: import { createCanvas } from 'canvas'; is importing nothing...which makes sense, since canvas is muted. but then again this is bad because i actually want to use it :D
it would be great if someone could nudge me in the right direction how to fix this paradox...
I am sorry, should've read the whole thread more thouroughly. I ended up with this Webpack config in gatsby-node.js which works just fine (the part with the resolve/alias is not relevant to this issue, the if-condition is the relevant thing):
exports.onCreateWebpackConfig = ({
stage,
rules,
loaders,
plugins,
actions
}) => {
actions.setWebpackConfig({
resolve: {
alias: {
'~components': path.resolve(__dirname, 'src/components'),
'~images': path.resolve(__dirname, 'src/images'),
'~hooks': path.resolve(__dirname, 'src/lib/hooks')
},
}
});
if (stage === "develop-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /canvas/,
use: loaders.null(),
},
],
},
})
}
};
weird but why does the proposed workaround not work for me?
onCreateWebpackConfig
gets called, stage
is build-html
, still it get this error:
exports.onCreateWebpackConfig = ({
stage,
rules,
loaders,
plugins,
actions,
}) => {
console.log("onCreateWebpackConfig", { stage })
// see: https://github.com/gatsbyjs/gatsby/issues/17661
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /canvas/,
use: loaders.null(),
},
],
},
})
}
}
success Writing page-data.json files to public directory - 0.187s - 381/381 2033.69/s
onCreateWebpackConfig { stage: 'build-html' }
ERROR #98124 WEBPACK
Generating SSR bundle failed
Can't resolve 'canvas' in '/dir/node_modules/konva/lib'
anyone has an idea why this is still happening here?
gatsby: 3.14.6
Recently I was working on a project , which uses
node-canvas
, and it is working fine in development mode. but if I want to build package andrun gatsby build
canvas will got some error on last steps with message :Generating SSR bundle failed
I used
loadImage
function from node canvas in an async function like :and use it in some componenet to load image in react-konva :
There was a issue in
node-canvas
repo , which says add this configuration to webpack , and I did it , but it pass build level and make some errors on browser console :after build , we got this error on console :
My project is in this repo : https://github.com/jafar-rezaei/snakeAndLadders.
File contents (if changed)
gatsby-config.js
: N/Apackage.json
: N/Agatsby-node.js
: N/Agatsby-browser.js
: N/Agatsby-ssr.js
: N/A