fix(vue-app): missing layout in error page with splittedChunks.layout (#8016)

This commit is contained in:
Dmitriy 2020-09-09 13:32:10 +03:00 committed by GitHub
parent 7e3532ea59
commit 757d5d46da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 199 additions and 12 deletions

View File

@ -129,11 +129,9 @@ export default {
<% } %> <% } %>
}, },
<% } %> <% } %>
<% if (loading) { %>
watch: { watch: {
'nuxt.err': 'errorChanged' 'nuxt.err': 'errorChanged'
}, },
<% } %>
<% if (features.clientOnline) { %> <% if (features.clientOnline) { %>
computed: { computed: {
isOffline () { isOffline () {
@ -215,9 +213,10 @@ export default {
<% if (loading) { %>this.$loading.finish()<% } %> <% if (loading) { %>this.$loading.finish()<% } %>
<% } %> <% } %>
}, },
<% if (splitChunks.layouts) { %>async <% } %>errorChanged () {
if (this.nuxt.err) {
<% if (loading) { %> <% if (loading) { %>
errorChanged () { if (this.$loading) {
if (this.nuxt.err && this.$loading) {
if (this.$loading.fail) { if (this.$loading.fail) {
this.$loading.fail(this.nuxt.err) this.$loading.fail(this.nuxt.err)
} }
@ -225,8 +224,18 @@ export default {
this.$loading.finish() this.$loading.finish()
} }
} }
},
<% } %> <% } %>
let errorLayout = (NuxtError.options || NuxtError).layout;
if (typeof errorLayout === 'function') {
errorLayout = errorLayout(this.context)
}
<% if (splitChunks.layouts) { %>
await this.loadLayout(errorLayout)
<% } %>
this.setLayout(errorLayout)
}
},
<% if (features.layouts) { %> <% if (features.layouts) { %>
<% if (splitChunks.layouts) { %> <% if (splitChunks.layouts) { %>
setLayout (layout) { setLayout (layout) {

View File

@ -613,7 +613,7 @@ function normalizeComponents (to, ___) {
} }
<% if (features.layouts) { %> <% if (features.layouts) { %>
function setLayoutForNextPage (to) { <% if (splitChunks.layouts) { %>async <% } %>function setLayoutForNextPage (to) {
// 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) {
@ -626,6 +626,9 @@ function setLayoutForNextPage (to) {
if (typeof layout === 'function') { if (typeof layout === 'function') {
layout = layout(app.context) layout = layout(app.context)
} }
<% if (splitChunks.layouts) { %>
await this.loadLayout(layout)
<% } %>
this.setLayout(layout) this.setLayout(layout)
} }
<% } %> <% } %>

View File

@ -20,7 +20,7 @@ describe('nuxt minimal vue-app bundle size limit', () => {
it('should stay within the size limit range', async () => { it('should stay within the size limit range', async () => {
const filter = filename => filename === 'vue-app.nuxt.js' const filter = filename => filename === 'vue-app.nuxt.js'
const legacyResourcesSize = await getResourcesSize(distDir, 'client', { filter }) const legacyResourcesSize = await getResourcesSize(distDir, 'client', { filter })
const LEGACY_JS_RESOURCES_KB_SIZE = 16.6 const LEGACY_JS_RESOURCES_KB_SIZE = 17.1
expect(legacyResourcesSize.uncompressed).toBeWithinSize(LEGACY_JS_RESOURCES_KB_SIZE) expect(legacyResourcesSize.uncompressed).toBeWithinSize(LEGACY_JS_RESOURCES_KB_SIZE)
}) })
}) })

View File

@ -42,6 +42,16 @@ describe('basic browser', () => {
expect(await page.$text('h1')).toBe('About') expect(await page.$text('h1')).toBe('About')
}) })
test('/about error layout after click', async () => {
const transitionPromise = page.evaluate(async ($nuxt) => {
await new Promise(resolve => $nuxt.$once('triggerScroll', resolve))
}, page.$nuxt)
await page.click('button')
await transitionPromise
expect(await page.$text('header')).toBe('Error layout')
})
test('/info prints empty page', async () => { test('/info prints empty page', async () => {
await page.nuxt.navigate('/info') await page.nuxt.navigate('/info')

View File

@ -0,0 +1,51 @@
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('split layouts error layout', () => {
beforeAll(async () => {
const config = await loadFixture('split-layouts-error')
nuxt = new Nuxt(config)
await nuxt.ready()
port = await getPort()
await nuxt.server.listen(port, 'localhost')
await browser.start()
page = await browser.page(url('/'))
})
test('Open /', async () => {
expect(await page.$text('h1')).toBe('Error Loop incoming page')
})
test('/info has error layout', async () => {
await page.nuxt.navigate('/info')
const transitionPromise = page.evaluate(async ($nuxt) => {
await new Promise(resolve => $nuxt.$once('triggerScroll', resolve))
}, page.$nuxt)
await page.click('button')
await transitionPromise
expect(await page.$text('header')).toBe('Error layout')
})
test('/error has error layout after router push', async () => {
await page.nuxt.navigate('/error')
expect(await page.$text('header')).toBe('Error layout')
})
test('/error has error layout after page load', async () => {
const localPage = await browser.page(url('/error'))
expect(await localPage.$text('header')).toBe('Error layout')
})
})

View File

@ -1,8 +1,24 @@
<template> <template>
<div> <div>
<h1>About</h1> <h1>About</h1>
<button
type="button"
@click="onClick"
>
error click
</button>
<nuxt-link to="/"> <nuxt-link to="/">
back back
</nuxt-link> </nuxt-link>
</div> </div>
</template> </template>
<script>
export default {
methods: {
onClick () {
this.$nuxt.context.error(new Error('test error'))
}
}
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<div>
<header>Error layout</header>
<nuxt />
</div>
</template>
<script>
export default {
name: 'ErrorLayout'
}
</script>

View File

@ -0,0 +1,18 @@
<template>
<div>
<h1>Error</h1>
<p>Details: {{ this.$route.path === '/squared' ? error.response.data : error.message }}</p>
<nuxt-link to="/">
back
</nuxt-link>
</div>
</template>
<script>
export default {
layout: 'error-layout',
// eslint-disable-next-line vue/require-prop-types
props: ['error']
}
</script>

View File

@ -0,0 +1,7 @@
export default {
build: {
splitChunks: {
layouts: true
}
}
}

View File

@ -0,0 +1,8 @@
<template>
<div>
<h1>About</h1>
<nuxt-link to="/">
back
</nuxt-link>
</div>
</template>

View File

@ -0,0 +1,12 @@
<template>
<h1>Error page</h1>
</template>
<script>
/* eslint no-undef: 0 */
export default {
asyncData ({ error }) {
error(new Error('test error'))
}
}
</script>

View File

@ -0,0 +1,14 @@
<template>
<div>
<h1>Error Loop incoming page</h1>
<nuxt-link id="error" to="/error">
Error during error
</nuxt-link>
<nuxt-link id="about" to="/about">
About
</nuxt-link>
<nuxt-link id="info" to="/info">
Info (with error)
</nuxt-link>
</div>
</template>

View File

@ -0,0 +1,24 @@
<template>
<div>
<h1>Info</h1>
<button
type="button"
@click="onClick"
>
click me
</button>
<nuxt-link to="/">
back
</nuxt-link>
</div>
</template>
<script>
export default {
methods: {
onClick () {
this.$nuxt.context.error(new Error('test error'))
}
}
}
</script>

View File

@ -0,0 +1,3 @@
import { buildFixture } from '../../utils/build'
buildFixture('split-layouts-error')