vue-i18n
vue-i18n copied to clipboard
Memory Leak SSR
vue & vue-i18n version
vue-i18n v8.11.2
Reproduction Link
any SSR usage
Question
In line
https://github.com/kazupon/vue-i18n/blob/master/src/mixin.js#L58 a new object is created server-side because we are in beforeCreate. This is necessary to get the languages rendered server-side as far as I can see but at the same time it generates a memory leak because the destructor is not called by SSR. Do you have any ideas how to overcome this issue?
Is there an older version of vue-i18n without this memory leak? Or a temporary workaround?
Dirty hotfix, but it works with Nuxt. Not making a PR because it should be written in a better way. Just made as a quick hotfix for myself in urgent situation. If anyone need urgent but dirty hotfix: https://github.com/Airnauts/vue-i18n/blob/hotfix/master_memory-leak/src/mixin.js
I suppose we are talking about this instance?: https://github.com/kazupon/vue-i18n/blob/f42e81f65a88eeeccc311b970d2d4fd4181712ed/src/mixin.js#L64
This extra instance is only created when there is a i18n component option defined in the component.
So this probably doesn't affect that many people but still bad if really happens.
But I wonder why is beforeDestroy not called on SSR. Is it normal that it isn't or something else is preventing it from being destroyed? Anyone knows?
I've just tested this on Nuxt and I can't reproduce the leak.
On the server-side, the VueI18n instance is created for each request and beforeDestroy is not called but I don't see any memory increase even after loading the page thousands of times.
Not that the current vue-i18n code doesn't even null-out the this._i18n property:
https://github.com/kazupon/vue-i18n/blob/e41736b291652798cf786591addd26e944437bf1/src/mixin.js#L117-L138
I'd love to see a repo that reproduces this issue, if you have any. The issue could actually be somewhere else in your code, for all I know.
@rchl The beforeDestroy hook hammered our employers system. What I did to evaluate the performance is I called return in the beforeDestroy hook without doing any further steps from the function and actually can see the improvement.
So employer has an dashboard and they transition from one page to another page and at that time the i18N components gets destroyed. it takes 20s for transition from one page to another. after returning out from the function it takes ~4s to transition.
@vishaldodiya this bug is about SSR and in SSR beforeDestroy hook is not even called. So not sure what you mean really.
If you mean on navigating on the client-side then it's some other issue.
I think this might be the same issue at nuxt: https://github.com/nuxt-community/i18n-module/issues/1039
I just reproduced with the latest nuxt/i18n versions.
I created a reproduction repo with documentation how it is setup and how to reproduce it: https://github.com/leonardlin/nuxt-vue-i18n-memory
still provided, that the nuxt-ssr-i18n is the same issue. Just looking at the code, @bpsushi hack looks correct.
In SSR situation beforeCreated is Server Side, but all the clean-up is client side.
Steps:
- I forked this vue-i18n,
- implemented @bpsushi fix
- included my hacked vue-i18n library to the reproduction repo: https://github.com/leonardlin/nuxt-vue-i18n-memory
- The problem is still reproduciable.
I went so far to remove all beforeCreate stuff and it still happened.
To me it seems that the watchers (that are cleaned up in beforeDestroyed) are not the only thing problematic. There might be something else going on.
weird.
Update: It seems to happen in combination with vue-i18n in dev-mode. In prod-mode I can't reproduce it either. Still investigating, will report if I can reproduce again.
@leonardlin Thanks a lot!
I'm doing OSS development while working at my day job. I will be working on this issue, although I may be a little slow to respond. 🙏
Update: I couldn't really trace it down to the function that is causing it (profiler crashed the node instance). From the memory-dump it looks like the watchers grow a lot and the arrays grow a lot. It is not related to the mixins (I removed them all for a test).
My latest hypothesis is that it's related to the setup with each request (install/constructor) and watchers because in dev-mode there are all these hot-reload watchers that don't exist in prod.
I'm not sure how critical this bug is, since it's a dev-mode issue only.
As mentioned in a couple first comments here, this issue seemed to be related to using the <i18n> element within a component. So this issue is quite specific and not necessarily what you are seeing with Nuxt. Also I'm not sure sure if this is even an issue anymore.
As for the Nuxt issue that you've linked (https://github.com/nuxt-community/i18n-module/issues/1039), as discussed in related PR (https://github.com/nuxt-community/i18n-module/pull/1040), that one is dev-specific issue due to how Nuxt works. See the PR for more info.
So I would not confuse those two.
any updates?
Hello, appreciate the work being done here. I think this should be noted on this documentation page. Thanks! https://vue-i18n.intlify.dev/guide/integrations/nuxt3