Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vue-app): context.beforeSerialize method #9332

Merged
merged 14 commits into from Jun 4, 2021
1 change: 1 addition & 0 deletions packages/types/app/index.d.ts
Expand Up @@ -72,6 +72,7 @@ export interface Context {
redirected: boolean
next: NextFunction
beforeRenderFns: Array<() => any>
afterRenderFns: Array<() => any>
fetchCounters: Record<string, number>
nuxt: {
layout: string
Expand Down
1 change: 1 addition & 0 deletions packages/vue-app/template/index.js
Expand Up @@ -183,6 +183,7 @@ async function createApp(ssrContext, config = {}) {
req: ssrContext ? ssrContext.req : undefined,
res: ssrContext ? ssrContext.res : undefined,
beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined,
afterRenderFns: ssrContext ? ssrContext.afterRenderFns : undefined,
ssrContext
})

Expand Down
11 changes: 9 additions & 2 deletions packages/vue-app/template/server.js
Expand Up @@ -85,6 +85,8 @@ export default async (ssrContext) => {
ssrContext.next = createNext(ssrContext)
// Used for beforeNuxtRender({ Components, nuxtState })
ssrContext.beforeRenderFns = []
// Used for afterNuxtRender({ Components, nuxtState })
ssrContext.afterRenderFns = []
// Nuxt object (window.{{globals.context}}, defaults to window.__NUXT__)
ssrContext.nuxt = { <% if (features.layouts) { %>layout: 'default', <% } %>data: [], <% if (features.fetch) { %>fetch: {}, <% } %>error: null<%= (store ? ', state: null' : '') %>, serverRendered: true, routePath: '' }
<% if (features.fetch) { %>
Expand Down Expand Up @@ -120,16 +122,21 @@ export default async (ssrContext) => {
const beforeRender = async () => {
// Call beforeNuxtRender() methods
await Promise.all(ssrContext.beforeRenderFns.map(fn => promisify(fn, { Components, nuxtState: ssrContext.nuxt })))
<% if (store) { %>

ssrContext.rendered = () => {
// Call afterNuxtRender() methods
ssrContext.afterRenderFns.forEach(fn => fn({ Components, nuxtState: ssrContext.nuxt }))

<% if (store) { %>
// Add the state from the vuex store
ssrContext.nuxt.state = store.state
<% } %>

<% if (isFullStatic && store) { %>
// Stop recording store mutations
ssrContext.unsetMutationObserver()
<% } %>
}
<% } %>
}

const renderErrorPage = async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/vue-app/template/utils.js
Expand Up @@ -259,6 +259,7 @@ export async function setContext (app, context) {
}
if (process.server) {
app.context.beforeNuxtRender = fn => context.beforeRenderFns.push(fn)
app.context.afterNuxtRender = fn => context.afterRenderFns.push(fn)
}
if (process.client) {
app.context.nuxtState = window.<%= globals.context %>
Expand Down
7 changes: 7 additions & 0 deletions test/dev/basic.ssr.test.js
Expand Up @@ -207,6 +207,13 @@ describe('basic ssr', () => {
expect(window.__NUXT__.test).toBe(true)
})

test('/special-state-after -> check window.__NUXT__.testAfter = true', async () => {
const window = await nuxt.server.renderAndGetWindow(url('/special-state-after'))
expect(window.document.title).toBe('Nuxt')
expect(window.__NUXT__.testBefore).toBeUndefined()
expect(window.__NUXT__.testAfter).toBe(true)
})

test('/error', async () => {
await expect(nuxt.server.renderRoute('/error', { req: {}, res: {} }))
.rejects.toThrow('Error mouahahah')
Expand Down
29 changes: 29 additions & 0 deletions test/fixtures/basic/pages/special-state-after.vue
@@ -0,0 +1,29 @@
<template>
<div>
<h1>Special state in `window.__NUXT__`</h1>
<client-only><pre>{{ nuxtState }}</pre></client-only>
</div>
</template>

<script>
export default {
data () {
return {
nuxtState: null
}
},
fetch () {
if (process.server) {
this.$root.context.beforeNuxtRender(({ nuxtState }) => {
nuxtState.testBefore = true
})
this.$root.context.afterNuxtRender(({ nuxtState }) => {
nuxtState.testAfter = true
})
}
},
beforeMount () {
this.nuxtState = window.__NUXT__
}
}
</script>