Skip to content

onScopeDispose can cause a SSR memory leak #14733

@cernymatej

Description

@cernymatej

Vue version

3.5.32

Link to minimal reproduction

https://stackblitz.com/edit/vitejs-vite-zqf6g74x?file=src%2Fcomponents%2FComponentA.vue&terminal=dev

Steps to reproduce

  1. download the reproduction from stackblitz (won't work there)
  2. run pnpm i && pnpm ssr
  3. see the heap size & alive app instances grow with each request

The script creates 1000 fresh ssr apps, renders them to string and tracks whether each of them gets garbage-collected.

2 sibling async SFC components with top-level await are needed for this to reproduce. One of them needs to capture a stop handle for an immediate watcher, which then ends up keeping the whole scope in memory and through it, the whole app. (probably)

ComponentA

<script setup>
    const enabled = await Promise.resolve(false)
    const el = ref(null)
    const stopWatch = watch(() => el.value, () => {}, { immediate: true })  // actually runs on the server
    onScopeDispose(() => { stopWatch() })
</script>

<template>
    <div ref="el">Component A {{ enabled }}</div>
</template>

Component B

<script setup>
    const enabled = await Promise.resolve(false)
</script>

<template>
    <div>Component B {{ enabled }}</div>
</template>

app:

<template>
    <div>
        <ComponentA />
        <ComponentB />
    </div>
</template>

What is expected?

All apps should get garbage collected.

What is actually happening?

Every app is kept in memory forever:

FINAL: created=10000 finalized=0 alive=10000

System Info

Any additional comments?

Maybe related to #14674?

In some cases, this can cause the whole NuxtApp to be kept in memory in Nuxt, along with all the rendered server payload, which adds up very quickly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ❗ p4-importantPriority 4: this fixes bugs that violate documented behavior, or significantly improves perf.scope: ssr

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions