mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
fix(vue-app): prevent mounting page twice on redirect (#5361)
This commit is contained in:
parent
7ce30935fa
commit
2d73e8aeba
@ -649,6 +649,10 @@ async function mountApp(__app) {
|
|||||||
const mount = () => {
|
const mount = () => {
|
||||||
_app.$mount('#<%= globals.id %>')
|
_app.$mount('#<%= globals.id %>')
|
||||||
|
|
||||||
|
// Add afterEach router hooks
|
||||||
|
router.afterEach(normalizeComponents)
|
||||||
|
router.afterEach(fixPrepatch.bind(_app))
|
||||||
|
|
||||||
// Listen for first Vue update
|
// Listen for first Vue update
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
// Call window.{{globals.readyCallback}} callbacks
|
// Call window.{{globals.readyCallback}} callbacks
|
||||||
@ -671,11 +675,9 @@ async function mountApp(__app) {
|
|||||||
_app.$loading = {} // To avoid error while _app.$nuxt does not exist
|
_app.$loading = {} // To avoid error while _app.$nuxt does not exist
|
||||||
if (NUXT.error) _app.error(NUXT.error)
|
if (NUXT.error) _app.error(NUXT.error)
|
||||||
|
|
||||||
// Add router hooks
|
// Add beforeEach router hooks
|
||||||
router.beforeEach(loadAsyncComponents.bind(_app))
|
router.beforeEach(loadAsyncComponents.bind(_app))
|
||||||
router.beforeEach(render.bind(_app))
|
router.beforeEach(render.bind(_app))
|
||||||
router.afterEach(normalizeComponents)
|
|
||||||
router.afterEach(fixPrepatch.bind(_app))
|
|
||||||
|
|
||||||
// If page already is server rendered
|
// If page already is server rendered
|
||||||
if (NUXT.serverRendered) {
|
if (NUXT.serverRendered) {
|
||||||
@ -684,20 +686,30 @@ async function mountApp(__app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First render on client-side
|
// First render on client-side
|
||||||
|
const clientFirstMount = () => {
|
||||||
|
normalizeComponents(router.currentRoute, router.currentRoute)
|
||||||
|
showNextPage.call(_app, router.currentRoute)
|
||||||
|
// Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
|
||||||
|
mount()
|
||||||
|
}
|
||||||
|
|
||||||
render.call(_app, router.currentRoute, router.currentRoute, (path) => {
|
render.call(_app, router.currentRoute, router.currentRoute, (path) => {
|
||||||
// If not redirected
|
// If not redirected
|
||||||
if (!path) {
|
if (!path) {
|
||||||
normalizeComponents(router.currentRoute, router.currentRoute)
|
clientFirstMount()
|
||||||
showNextPage.call(_app, router.currentRoute)
|
|
||||||
// Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
|
|
||||||
mount()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the path and then mount app
|
// Add a one-time afterEach hook to
|
||||||
router.push(path, () => mount(), (err) => {
|
// mount the app wait for redirect and route gets resolved
|
||||||
if (!err) return mount()
|
const unregisterHook = router.afterEach((to, from) => {
|
||||||
errorHandler(err)
|
unregisterHook()
|
||||||
|
clientFirstMount()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Push the path and let route to be resolved
|
||||||
|
router.push(path, undefined, (err) => {
|
||||||
|
if (err) errorHandler(err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
14
test/fixtures/spa/middleware/middleware.js
vendored
Normal file
14
test/fixtures/spa/middleware/middleware.js
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
export default function ({ route, redirect }) {
|
||||||
|
const redirectPathRegexp = /^\/redirect(\d+)$/
|
||||||
|
const match = route.path.match(redirectPathRegexp)
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const number = parseInt(match[1])
|
||||||
|
if (number === 1) {
|
||||||
|
redirect('/redirect-done')
|
||||||
|
} else {
|
||||||
|
redirect(`/redirect${number - 1}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
test/fixtures/spa/nuxt.config.js
vendored
3
test/fixtures/spa/nuxt.config.js
vendored
@ -15,6 +15,9 @@ export default {
|
|||||||
chunk: '[name].js'
|
chunk: '[name].js'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
router: {
|
||||||
|
middleware: 'middleware'
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
'~/plugins/error.js'
|
'~/plugins/error.js'
|
||||||
]
|
]
|
||||||
|
17
test/fixtures/spa/pages/redirect-done.vue
vendored
Normal file
17
test/fixtures/spa/pages/redirect-done.vue
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<div>Redirect Done Page</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
layout: 'default',
|
||||||
|
created() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('redirect-done created')
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('redirect-done mounted')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -99,6 +99,43 @@ describe('spa', () => {
|
|||||||
|
|
||||||
const { $data } = window.$nuxt.$route.matched[0].instances.default
|
const { $data } = window.$nuxt.$route.matched[0].instances.default
|
||||||
expect(Object.keys($data).length).toBe(1)
|
expect(Object.keys($data).length).toBe(1)
|
||||||
|
consola.log.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/redirect-done (no redirect)', async () => {
|
||||||
|
const { html } = await renderRoute('/redirect-done')
|
||||||
|
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||||
|
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||||
|
consola.log.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/redirect1 (redirect 1 time)', async () => {
|
||||||
|
const { html } = await renderRoute('/redirect1')
|
||||||
|
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||||
|
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||||
|
consola.log.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/redirect2 (redirect 2 times)', async () => {
|
||||||
|
const { html } = await renderRoute('/redirect2')
|
||||||
|
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||||
|
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||||
|
consola.log.mockClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/redirect10 (redirect 10 times)', async () => {
|
||||||
|
const { html } = await renderRoute('/redirect10')
|
||||||
|
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||||
|
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||||
|
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||||
|
consola.log.mockClear()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Close server and ask nuxt to stop listening to file changes
|
// Close server and ask nuxt to stop listening to file changes
|
||||||
|
Loading…
Reference in New Issue
Block a user