How to completely clean up a Three.js scene from a web app once the scene is no longer needed

Continuing the discussion from API Documentation:

If we are completely done wanting to have a Three.js scene exist in an application (f.e., suppose we have a single page application where the page was rendering a Three.js scene, and we’ve switched to another view and we no longer need to render any Three.js scene), how do we properly and completely clean the scene up so that no traces of it left behind in memory?

Here’s some things I can think of:

  1. Call dispose() on all geometries
  2. Call dispose() on all materials

What else? What’s the comprehensive list of things to do to completely remove any and all Three.js rendering from a page (and even THREE itself if it is no longer needed)?

1 Like

I think the best way to do it is to let the javascript garbage collector handle this for you.
All you have to do is make sure there are no references left to your scene object and any objects inside it.

If you have some class in your application that holds references to materials, for example, you’ll have to remove them by simply calling delete this.materials['my_mateiral_name_or_id']. The same thing applies to anything that is in your scene that might live elsewhere in your application.

I think this is essentially what dispose() does for you internally.

Lastly, forcing a context loss on the webgl context and getting rid of the renderer afterward will ensure you’ll be freeing up GPU resources, and allowing you to initialize another renderer afterward without resource usage being stacked up.

See the discussion on GH too:

And also these examples:


textures also need to be disposed

@Harold Simply losing rederences I don’t think always works. For example, if you keep a reference to a renderer in order to use it later to render a different scene, not having called dispose() will have leaked geometries/materials/textures/etc into the GPU, right?

As for losing a reference to everything (f.e. Three, canvases, gl contexts, all meshes/geometries/materials/etc) will that successfully clean things up without having to call dispose() on anything? @pailhead @looeee?

Anything that is an object that no longer holds a reference anywhere, will get cleaned up by the GC.
A texture is also an object (THREE.Texture), that holds a reference to either Image, Canvas or ImageData or any other kind of image (or video) source.

Nullifying these references (setting the property that holds the reference to null or undefined), makes the dereferenced object eligible for garbage collection. There is no way to “force” this in any other way.

This is effectively what a dispose() function should do.

As for the renderer, calling dispose() should force a “context loss” that will free up the GL context (and therefore free up GPU resources) once the GC kicks in.

Psuedo dispose() example (not to be taken literally):

this.dispose = function () {
    // Iterate through all properties of this object.
    Object.keys(this).forEach((key) => {
        // Recursively call dispose() if possible.
        if (typeof this[key].dispose === 'function') {
        // Remove any reference.
        this[key] = null;

Of course, you shouldn’t do it like this, but it simply illustrates how a dispose function could work.

If an object holds any reference to another object that is still being used (e.g. a DOM element that is still present), it isn’t eligible for garbage collection and therefore will never be cleaned up.

1 Like

So, if I lose all references to all Three.js objects, and also the canvas (remove it from DOM), then I suppose I should be okay (I’m guessing losing a reference to canvas plus all Three obects cleans up the GPU too). I’m guessing in that case I don’t need to call any dispose functions, and that dispose is useful only if we’re keeping the canvas and the renderer, and just want to change the scene to show other stuff and to unshow some other stuff (f.e. switching views in the scene).

@trusktr it’s probably better to test that rather than guess.


Testing takes time. I figured someone might know. The docs don’t go into detail on that (yet), and reading source will take some time. I reading little by little… :blush:

1 Like

Dealing with scene cleanup is one of the grey box areas of three.js currently. There isn’t really good documentation and it does take a lot of time to test.

I’m not saying that it should be you that does this testing… But it would be great if somebody wrote a comprehensive guide and added it to the docs.

1 Like

Alright, the following is what I have so far, and I’m doing it to see if there’s any difference in memory use compared to not doing it (my guess is there won’t be and the Garbage Collector will work great, but just in case). Am I missing anything?

console.log('dispose renderer!')

scene.traverse(object => {
	if (!object.isMesh) return
	console.log('dispose geometry!')

	if (object.material.isMaterial) {
	} else {
		// an array of materials
		for (const material of object.material) cleanMaterial(material)

const cleanMaterial = material => {
	console.log('dispose material!')

	// dispose textures
	for (const key of Object.keys(material)) {
		const value = material[key]
		if (value && typeof value === 'object' && 'minFilter' in value) {
			console.log('dispose texture!')

1 Like