gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.27k stars 10.31k forks source link

External Canvas code keeps triggering on page change #20455

Closed MrUltimate closed 4 years ago

MrUltimate commented 4 years ago

Summary

I am using an external WebGL Canvas script for me index page. Because the script looks for a canvas element on start, I've created a React Component to add the script to the DOM on mount. However, every time I change the page, and come back, the code is re-triggered and creates warnings for WebGL, heavily impacting performance. To combat this, I've created functions that start and stop the WebGL Simulation, however, sometime keeps the WebGL code running, causing interference. Does anyone have any experience with this, and any workarounds? What's the best way to work with this within Gatsby?

Relevant information

The external script: https://github.com/MrUltimate/portfolio-2020/blob/master/static/assets/scripts/fluid-init.js The React Component: https://github.com/MrUltimate/portfolio-2020/blob/master/src/components/fluid.jsx Full Repo: https://github.com/MrUltimate/portfolio-2020

jonniebigodes commented 4 years ago

@MrUltimate what i belive is happening is in fact by design. When the route is changed it will unmount the tree. Which in your case will trigger the script to run again. You probably could prevent it with the usage of wrapPageElement browser api and it's counterpart for ssr (Server side rendering), you can read more about the browser api here and the ssr api here. Or probably use the gatsby-plugin-layout that to the best of my knowledge already takes care of the implementation and could actually help you with your issue.

Also a tip for you if you don't mind. The repo is a great addition, but for some cases like your own as it's consuming data from a external data source it would be better for us if you could supply a minimal reproduction with some dummy data following these steps so that when me or another person picks up on the issue he/she goes directly for it as to avoid having to comment out portions of the code.

Feel free to provide feedback so that we can close this issue or continue to work on it until we find a suitable solution

MrUltimate commented 4 years ago

@jonniebigodes Thanks for your response. And apologies for the newbie mistakes. I have installed and used gatsby-plugin-layout however it seems like this is still occurring. To clarify my intent, on navigating away from the index page, I want the external WebGL script to stop, and then re-initialize when navigated back to the index page. It seems like something in Gatsby retains the WebGL code and shaders, which on navigation back to the index page are re-initialize on top of the existing code that was initialized from the first run. How can I stop this behavior, specifically for this external script?

I have now included a read-only API key in my build which you can use to develop and build.

You can also look at a live example here: https://helloshivam-2020.netlify.com

Thanks for all your help in advance!

jonniebigodes commented 4 years ago

@MrUltimate sorry for the late response, but i've been pulled the latest code version you've setup and i was checking it and i'm inclined to believe the issue is not actually Gatsby. In this case Gatsby acts as a "conduit". The issue is more of a React implementation. In the component's code you have the componentDidMount livecycle method were the script will be injected correct? Now when you load the page it the method will trigger and inject the script. But when the page is changed the component is unmounted but the method componentDidUnMount that you have there is never called. The message is not showing for me in the console. What i did was add the componentWillUnmount livecycle method and in there the script is removed and the log message is triggered. Based on this i would update the code to do the proper cleanup in the livecycle method and see if the issue still persists.

Also no need to apologize for any mistakes, we're all learning here.

One more quick tip if you'll allow me. Do not commit the public folder to the repo. the .cache is ok, as it will help out the production build with some CI environments, but the public could cause some issues with some stale data, for instance some images/content that will be present even if you deleted it in your CMS.

On a side note, a more personal note, love the work you have there. It's really great stuff 👍

MrUltimate commented 4 years ago

Thanks @jonniebigodes for the kind words, I'm glad you liked it! I will change to componentWillUnmount() for the clean up, which is a little hard because I don't have access to the functions from that script. I.e. I can't call the standard window methods or in this case, WebGL's loseContext() method which will help me clean the WebGL code. Would happen to have any experience in WebGL?

jonniebigodes commented 4 years ago

@MrUltimate take a look at #13136 for some context on how you probably could do the cleanup portion. And if you're asking me if i have any experience in WebGL, sadly no i do not. I tinkered with it a bit ago but it was only for side projects

LekoArts commented 4 years ago

Thank you for opening this!

As always thanks @jonniebigodes for the great explanations! This is indeed not an issue with Gatsby per se but a React question as answered above. Some more notes from me:

We're marking this issue as answered and closing it for now but please feel free to comment here if you would like to continue this discussion. We also recommend heading over to our communities if you have questions that are not bug reports or feature requests. We hope we managed to help and thank you for using Gatsby!