mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-24 22:55:13 +00:00
fix(vue-app): prevent double page mount (#10874)
This commit is contained in:
parent
5441c062fa
commit
1f663e7f27
@ -649,7 +649,8 @@ function normalizeComponents (to, ___) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
<% if (features.layouts) { %>
|
<% if (features.layouts) { %>
|
||||||
<% if (splitChunks.layouts) { %>async <% } %>function setLayoutForNextPage (to) {
|
const routeMap = new WeakMap()
|
||||||
|
<% if (splitChunks.layouts) { %>async <% } %>function getLayoutForNextPage (to, from, next) {
|
||||||
// Set layout
|
// Set layout
|
||||||
let hasError = Boolean(this.$options.nuxt.err)
|
let hasError = Boolean(this.$options.nuxt.err)
|
||||||
if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) {
|
if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) {
|
||||||
@ -662,9 +663,19 @@ function normalizeComponents (to, ___) {
|
|||||||
if (typeof layout === 'function') {
|
if (typeof layout === 'function') {
|
||||||
layout = layout(app.context)
|
layout = layout(app.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
routeMap.set(to, layout);
|
||||||
|
|
||||||
<% if (splitChunks.layouts) { %>
|
<% if (splitChunks.layouts) { %>
|
||||||
await this.loadLayout(layout)
|
await this.loadLayout(layout)
|
||||||
<% } %>
|
<% } %>
|
||||||
|
if (next) next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLayoutForNextPage(to) {
|
||||||
|
const layout = routeMap.get(to)
|
||||||
|
routeMap.delete(to)
|
||||||
|
|
||||||
this.setLayout(layout)
|
this.setLayout(layout)
|
||||||
}
|
}
|
||||||
<% } %>
|
<% } %>
|
||||||
@ -903,6 +914,7 @@ async function mountApp (__app) {
|
|||||||
// Add afterEach router hooks
|
// Add afterEach router hooks
|
||||||
router.afterEach(normalizeComponents)
|
router.afterEach(normalizeComponents)
|
||||||
<% if (features.layouts) { %>
|
<% if (features.layouts) { %>
|
||||||
|
router.beforeResolve(getLayoutForNextPage.bind(_app))
|
||||||
router.afterEach(setLayoutForNextPage.bind(_app))
|
router.afterEach(setLayoutForNextPage.bind(_app))
|
||||||
<% } %>
|
<% } %>
|
||||||
router.afterEach(fixPrepatch.bind(_app))
|
router.afterEach(fixPrepatch.bind(_app))
|
||||||
@ -963,10 +975,15 @@ async function mountApp (__app) {
|
|||||||
}
|
}
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
const clientFirstLayoutSet = <% if (splitChunks.layouts) { %>async<% } %> () => {
|
||||||
|
<% if (splitChunks.layouts) { %>await<% } %> getLayoutForNextPage.call(_app, router.currentRoute)
|
||||||
|
setLayoutForNextPage.call(_app, router.currentRoute)
|
||||||
|
}
|
||||||
|
|
||||||
// First render on client-side
|
// First render on client-side
|
||||||
const clientFirstMount = () => {
|
const clientFirstMount = () => {
|
||||||
normalizeComponents(router.currentRoute, router.currentRoute)
|
normalizeComponents(router.currentRoute, router.currentRoute)
|
||||||
setLayoutForNextPage.call(_app, router.currentRoute)
|
clientFirstLayoutSet()
|
||||||
checkForErrors(_app)
|
checkForErrors(_app)
|
||||||
// Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
|
// Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
|
||||||
mount()
|
mount()
|
||||||
|
@ -26,14 +26,14 @@ describe('nuxt basic resources size limit', () => {
|
|||||||
const LEGACY_JS_RESOURCES_GZIP_KB_SIZE = 88
|
const LEGACY_JS_RESOURCES_GZIP_KB_SIZE = 88
|
||||||
expect(legacyResourcesSize.gzip).toBeWithinSize(LEGACY_JS_RESOURCES_GZIP_KB_SIZE)
|
expect(legacyResourcesSize.gzip).toBeWithinSize(LEGACY_JS_RESOURCES_GZIP_KB_SIZE)
|
||||||
|
|
||||||
const LEGACY_JS_RESOURCES_BROTLI_KB_SIZE = 73
|
const LEGACY_JS_RESOURCES_BROTLI_KB_SIZE = 76
|
||||||
expect(legacyResourcesSize.brotli).toBeWithinSize(LEGACY_JS_RESOURCES_BROTLI_KB_SIZE)
|
expect(legacyResourcesSize.brotli).toBeWithinSize(LEGACY_JS_RESOURCES_BROTLI_KB_SIZE)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should stay within the size limit range in modern mode', async () => {
|
it('should stay within the size limit range in modern mode', async () => {
|
||||||
const modernResourcesSize = await getResourcesSize(distDir, 'modern', { gzip: true, brotli: true })
|
const modernResourcesSize = await getResourcesSize(distDir, 'modern', { gzip: true, brotli: true })
|
||||||
|
|
||||||
const MODERN_JS_RESOURCES_KB_SIZE = 215
|
const MODERN_JS_RESOURCES_KB_SIZE = 225
|
||||||
expect(modernResourcesSize.uncompressed).toBeWithinSize(MODERN_JS_RESOURCES_KB_SIZE)
|
expect(modernResourcesSize.uncompressed).toBeWithinSize(MODERN_JS_RESOURCES_KB_SIZE)
|
||||||
|
|
||||||
const MODERN_JS_RESOURCES_GZIP_KB_SIZE = 77
|
const MODERN_JS_RESOURCES_GZIP_KB_SIZE = 77
|
||||||
|
60
test/e2e/page-mount-with-layouts.test.js
Normal file
60
test/e2e/page-mount-with-layouts.test.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import Browser from '../utils/browser'
|
||||||
|
import { loadFixture, getPort, Nuxt } from '../utils'
|
||||||
|
|
||||||
|
let port
|
||||||
|
const browser = new Browser()
|
||||||
|
const url = route => 'http://localhost:' + port + route
|
||||||
|
|
||||||
|
let nuxt = null
|
||||||
|
let page = null
|
||||||
|
|
||||||
|
describe('page mount times while changing layouts', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
const config = await loadFixture('page-mount-with-layouts')
|
||||||
|
nuxt = new Nuxt(config)
|
||||||
|
await nuxt.ready()
|
||||||
|
|
||||||
|
port = await getPort()
|
||||||
|
await nuxt.server.listen(port, 'localhost')
|
||||||
|
await browser.start()
|
||||||
|
page = await browser.page(url('/page-1'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Open /page-1 and mount 1 times', async () => {
|
||||||
|
expect(await page.$text('h1')).toBe('Layout 1')
|
||||||
|
expect(await page.$text('h2')).toBe('Page 1')
|
||||||
|
expect(await page.evaluate(() => window.mountedCount)).toEqual(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Change layout and mount 2 times', async () => {
|
||||||
|
page = await browser.page(url('/page-1'))
|
||||||
|
|
||||||
|
await page.nuxt.navigate('/page-2')
|
||||||
|
|
||||||
|
expect(await page.$text('h1')).toBe('Layout 2')
|
||||||
|
expect(await page.$text('h2')).toBe('Page 2')
|
||||||
|
expect(await page.evaluate(() => window.mountedCount)).toEqual(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Change layout multiple times', async () => {
|
||||||
|
page = await browser.page(url('/page-2'))
|
||||||
|
|
||||||
|
await page.nuxt.navigate('/page-1')
|
||||||
|
|
||||||
|
expect(await page.$text('h1')).toBe('Layout 1')
|
||||||
|
expect(await page.$text('h2')).toBe('Page 1')
|
||||||
|
expect(await page.evaluate(() => window.mountedCount)).toEqual(2)
|
||||||
|
|
||||||
|
await page.nuxt.navigate('/page-2')
|
||||||
|
|
||||||
|
expect(await page.evaluate(() => window.mountedCount)).toEqual(3)
|
||||||
|
|
||||||
|
await page.nuxt.navigate('/page-1')
|
||||||
|
|
||||||
|
expect(await page.evaluate(() => window.mountedCount)).toEqual(4)
|
||||||
|
|
||||||
|
await page.nuxt.navigate('/page-1', false)
|
||||||
|
|
||||||
|
expect(await page.evaluate(() => window.mountedCount)).toEqual(4)
|
||||||
|
})
|
||||||
|
})
|
7
test/fixtures/page-mount-with-layouts/layouts/layout-1.vue
vendored
Normal file
7
test/fixtures/page-mount-with-layouts/layouts/layout-1.vue
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Layout 1</h1>
|
||||||
|
|
||||||
|
<Nuxt />
|
||||||
|
</div>
|
||||||
|
</template>
|
7
test/fixtures/page-mount-with-layouts/layouts/layout-2.vue
vendored
Normal file
7
test/fixtures/page-mount-with-layouts/layouts/layout-2.vue
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Layout 2</h1>
|
||||||
|
|
||||||
|
<Nuxt />
|
||||||
|
</div>
|
||||||
|
</template>
|
11
test/fixtures/page-mount-with-layouts/nuxt.config.js
vendored
Normal file
11
test/fixtures/page-mount-with-layouts/nuxt.config.js
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
features: {
|
||||||
|
transitions: false
|
||||||
|
},
|
||||||
|
|
||||||
|
build: {
|
||||||
|
splitChunks: {
|
||||||
|
layouts: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
test/fixtures/page-mount-with-layouts/page-mount-with-layouts.test.js
vendored
Normal file
3
test/fixtures/page-mount-with-layouts/page-mount-with-layouts.test.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { buildFixture } from '../../utils/build'
|
||||||
|
|
||||||
|
buildFixture('page-mount-with-layouts')
|
22
test/fixtures/page-mount-with-layouts/pages/page-1.vue
vendored
Normal file
22
test/fixtures/page-mount-with-layouts/pages/page-1.vue
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Page 1</h2>
|
||||||
|
|
||||||
|
<NuxtLink
|
||||||
|
id="link"
|
||||||
|
to="/page-2"
|
||||||
|
>
|
||||||
|
To page 2
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
layout: 'layout-1',
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
window.mountedCount = (window.mountedCount || 0) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
22
test/fixtures/page-mount-with-layouts/pages/page-2.vue
vendored
Normal file
22
test/fixtures/page-mount-with-layouts/pages/page-2.vue
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Page 2</h2>
|
||||||
|
|
||||||
|
<NuxtLink
|
||||||
|
id="link"
|
||||||
|
to="/page-1"
|
||||||
|
>
|
||||||
|
To page 1
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
layout: 'layout-2',
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
window.mountedCount = (window.mountedCount || 0) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user