mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
fix(vue-app): fix asyncData
memory leak on client-side (#4966)
Co-authored-by: Sébastien Chopin <seb@chopin.io>
This commit is contained in:
parent
17cc12f005
commit
408680046c
@ -1,7 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
const noopData = () => ({})
|
||||
|
||||
// window.{{globals.loadedCallback}} hook
|
||||
// Useful for jsdom testing or plugins (https://github.com/tmpvar/jsdom#dealing-with-asynchronous-script-loading)
|
||||
if (process.client) {
|
||||
@ -24,12 +22,17 @@ export function interopDefault(promise) {
|
||||
}
|
||||
|
||||
export function applyAsyncData(Component, asyncData) {
|
||||
const ComponentData = Component.options.data || noopData
|
||||
// Prevent calling this method for each request on SSR context
|
||||
if (!asyncData && Component.options.hasAsyncData) {
|
||||
if (
|
||||
// For SSR, we once all this function without second param to just apply asyncData
|
||||
// Prevent doing this for each SSR request
|
||||
!asyncData && Component.options.__hasNuxtData
|
||||
) {
|
||||
return
|
||||
}
|
||||
Component.options.hasAsyncData = true
|
||||
|
||||
const ComponentData = Component.options._originDataFn || Component.options.data || function () { return {} }
|
||||
Component.options._originDataFn = ComponentData
|
||||
|
||||
Component.options.data = function () {
|
||||
const data = ComponentData.call(this)
|
||||
if (this.$ssrContext) {
|
||||
@ -37,6 +40,9 @@ export function applyAsyncData(Component, asyncData) {
|
||||
}
|
||||
return { ...data, ...asyncData }
|
||||
}
|
||||
|
||||
Component.options.__hasNuxtData = true
|
||||
|
||||
if (Component._Ctor && Component._Ctor.options) {
|
||||
Component._Ctor.options.data = Component.options.data
|
||||
}
|
||||
|
20
test/fixtures/spa/pages/async.vue
vendored
Normal file
20
test/fixtures/spa/pages/async.vue
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<pre>
|
||||
{{ debug }}
|
||||
</pre>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
asyncData() {
|
||||
return {
|
||||
[Math.random()]: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
debug() {
|
||||
return JSON.stringify(this.$data, null, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -82,6 +82,23 @@ describe('spa', () => {
|
||||
expect(consola.log).toHaveBeenCalledWith('mounted')
|
||||
consola.log.mockClear()
|
||||
})
|
||||
|
||||
test('/async no asyncData leak', async () => {
|
||||
const window = await nuxt.server.renderAndGetWindow(url('/async'))
|
||||
|
||||
const navigate = url => new Promise((resolve, reject) => {
|
||||
window.$nuxt.$router.push(url, resolve, reject)
|
||||
})
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
await navigate('/')
|
||||
await navigate('/async')
|
||||
}
|
||||
|
||||
const { $data } = window.$nuxt.$route.matched[0].instances.default
|
||||
expect(Object.keys($data).length).toBe(1)
|
||||
})
|
||||
|
||||
// Close server and ask nuxt to stop listening to file changes
|
||||
afterAll(async () => {
|
||||
await nuxt.close()
|
||||
|
Loading…
Reference in New Issue
Block a user