Description
Version
3.1.6
Reproduction link
https://codesandbox.io/s/nostalgic-mahavira-y0m7q
Steps to reproduce
Memory leak
Call new VueRouter()
multiple times. It is impossible to clean up its popstate listener.
Basepath bug
If you have multiple vue applications, each using vue-router, they must all share the same base path, even if you ensure only one of them is active at a time by destroying / remounting when navigating between them. Otherwise they will all attempt to ensure that every route starts with their base path.
Same goes for if you have one vue-router and one react-router. The vue-router will force all urls to start with its base path within the react-owned pages, even if you have destroyed the vue application before navigating to the react application.
What is expected?
I think the best solution is to call window.addEventListener('popstate', handler)
when const intance = new Vue({router})
is called, instead of when new VueRouter()
is called. And then call window.removeEventListener('popstate', handler)
when instance.$destroy()
is called.
Alternatively, it could be cleaned up like so:
// Alternative solution (not my preferred one, but works)
const router = new VueRouter({...})
// later, to clean up event listeners:
router.detach()
// later, to reattach event listeners
router.attach()
What is actually happening?
window.addEventListener is called during new VueRouter()
, and there is no way to ever remove that event listener.
See related single-spa/single-spa#488. I am a maintainer of single-spa, which has dozens of organizations using one or more instances of vue-router. For us, cleaning up the event listener when the application is unmounted is important to being able to have isolated apps on the same page.