-
Notifications
You must be signed in to change notification settings - Fork 101
Description
Version
vue-final-modal: v2.4.1
vue: v2.6.12
nuxt: v2.15.8 (It's likely to happen in any SSR context)
OS
Mac
Reproduction Link
Apologies, I currently do not have a time capacity to provide a repo, nor to fix the issue - I'm in a bit of a hellish crunch right now. I did however found the the culprit.
Steps to reproduce
- Install the plugin
# plugins/vue-final-modal.js
import vfmPlugin from 'vue-final-modal/lib'
Vue.use(vfmPlugin)
- Create a component that utilises
vue-final-modal
and renders it during SSR cycle (noclient-only
). Props, includingssr
are irrelevant. - Use Chrome dev tools to profile apps memory
yarn build && node --inspect node_modules/.bin/nuxt start
- Load test the app with
siege
orab
ab -c 50 -n 1000000 -k http://127.0.0.1:3000
What is Expected?
App won't run out of memory
What is actually happening?
App will run out of memory (4gb) :)
Cause of the issue
VueFinalModal.vue saves the reference to component instance in created
hook:
vue-final-modal/lib/VueFinalModal.vue
Lines 266 to 268 in 731714e
created() { | |
this.api.modals.push(this) | |
}, |
As per vue docs, during SSR cycle, only two lifecycle methods are executed -
beforeCreate
and created
- meaning running code that produces side effects inside of those methods will create memory leaks, given that beforeDestroy
and destroy
won't be run to perform cleanup.
Because this.api
is a singular instance initialised during server boot in the plugin file (not on each request), each time VueFinalModal is rendered during SSR, its instance is added to the api.modals
and kept there indefinitely - vide the memory leak.
I confirmed this by removing this line and performing load tests again - no more memory leaks.
Temporary fix
If VueFinalModal is not rendered server-side, it will not register in modal api and not produce any memory leaks.
<client-only>
<vue-final-modal ... />
</client-only>
A proper, simple fix I imagine would be to conditionally register modal in the API only on the client. In the long run however, I do worry whether using global instance of api
isn't playing with fire - at least in SSR usages.