Organize your Three.js Project - Part 3

Extract the Three.js camera into a factory function that subscribes to a shared resize observer and returns a dispose method.

Learn how to handle Vite's hot module replacement with import.meta.hot to clean up cameras, renderers, and WebGL contexts, preventing duplication and boosting dev performance.

Modern Three.js Course
Lesson 13 of 14

Modern Three.js Course

Go from zero to a modular Three.js app with Vite and TypeScript.

Share with a coworker

Transcript

[00:00] So for the camera we're going to duplicate this here and call it create camera. So for the camera we can remove the WebGL renderer, this interface, we are going to call this create camera. Maybe we will, well, we actually just need the resize of server. So maybe it doesn't even needs to be an object. It could be just the resize of server.

[00:30] We can remove this here, but we are going to need the width and height that's staying and we need to register as well. So let's remove this. We also need a dispose. So okay, it looks good to get started with the camera. So for the camera, we need to move everything that we have in here.

[00:52] Where is it? Here. So we are gonna take all this and we are gonna move it. I'm gonna close this and also resize observer. And here we're gonna do perspective camera imported from tree so we already get the sizes here from the resize of server so that's nice yes I know you're complaining because basically we need to do the same as here.

[01:18] So return type server, something like this. Okay, now it's good. We need to do something whenever we are resizing. So if we go back here, what we were doing is setting the aspect ratio of the camera and also updating the projection matrix of it so we're gonna go here and do exactly that but we're going to use the width and the height So let me see if I'm not forgetting anything. So we have the onResize, we are setting the camera.

[01:55] Now everything looks good. So we're gonna return, of course, the camera. And what the dispose is gonna be, I think here is just gonna be the unsubscribe, because I don't think there is anything that we need to add for the camera disposal. Okay, so let's use it. Let's go to main TS and Here where we do the scene we're gonna do cons camera Equal create camera and we pass down the resize of server.

[02:34] We need to import it from here. And if everything went right, if we refresh here, our scene continues working. So we've successfully managed to abstract all the code that we had here into different factory functions. We could go even further and abstract more stuff from here and clean in the main TS. So we no longer need the sizes here The scene is so simple that you you only need to call it here and pass it down So it doesn't make sense to abstract it The objects is up to you.

[03:14] We could do the Graphic interface this twig thing thing you can extract it as well but I will let you do it as an exercise, and let me know later if you manage to do it. What I didn't explain though is why we needed those disposals. And the thing is that we're using Vite and this has a hot model replacement. So we need to clean up a lot of stuff to prevent the WebGL context duplication. This is really important to make the scene, especially in dev mode, more performant.

[03:50] So what we're going to do just below here is that we're going to clean up for hot model replacement. So the way you detect if you're in Hot Model Represents is import meta hot and you need to do something like onDispose we're gonna dispose the camera and dispose the render. But we need to return it from the camera. So here we have an unsubscribe dispose, but we are gonna call it dispose camera. And here we have also dispose, but we're gonna say disposeRender.

[04:40] Okay, so this disposeCamera expression is not callable. This expression is not callable. It's return a boolean and this one Okay, so create camera what did it? Okay, so it needs to be something like this, right? Yes, okay, so whenever we are hot model when the hot model replacement hits It's gonna dispose the previous camera and dispose the previous render We can do you also like a scene dispose or go through it I don't know if it even has a dispose now but I know that the object does so you can even clean up the cube Let's see if the cube geometry has this pose.

[05:35] So yes, you can start disposing the rest of elements in the scene if you want.