Skip to content

Commit

Permalink
feat(vue-app): context.beforeSerialize method (#9332)
Browse files Browse the repository at this point in the history
Co-authored-by: Sébastien Chopin <seb@nuxtjs.com>
Co-authored-by: Daniel Roe <daniel@roe.dev>
Co-authored-by: pooya parsa <pyapar@gmail.com>
  • Loading branch information
4 people committed Jun 4, 2021
1 parent fa12cf1 commit 9f02e5d
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 6 deletions.
2 changes: 2 additions & 0 deletions packages/types/app/index.d.ts
Expand Up @@ -72,6 +72,7 @@ export interface Context {
redirected: boolean
next: NextFunction
beforeRenderFns: Array<() => any>
beforeSerializeFns: Array<() => any>
fetchCounters: Record<string, number>
nuxt: {
layout: string
Expand All @@ -87,6 +88,7 @@ export interface Context {
error(params: NuxtError): void
nuxtState: NuxtState
beforeNuxtRender(fn: (params: { Components: VueRouter['getMatchedComponents'], nuxtState: NuxtState }) => void): void
beforeSerialize(fn: (nuxtState: NuxtState) => void): void
enablePreview?: (previewData?: Record<string, any>) => void
$preview?: Record<string, any>
}
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,
beforeSerializeFns: ssrContext ? ssrContext.beforeSerializeFns : 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 = []
// for beforeSerialize(nuxtState)
ssrContext.beforeSerializeFns = []
// 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 beforeSerialize() hooks
ssrContext.beforeSerializeFns.forEach(fn => fn(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.beforeSerialize = fn => context.beforeSerializeFns.push(fn)
}
if (process.client) {
app.context.nuxtState = window.<%= globals.context %>
Expand Down
12 changes: 9 additions & 3 deletions test/dev/basic.ssr.test.js
Expand Up @@ -201,10 +201,16 @@ describe('basic ssr', () => {
})
})

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

test('/before-serialize -> check window.__NUXT__.beforeSerialize = true', async () => {
const window = await nuxt.server.renderAndGetWindow(url('/before-serialize'))
expect(window.document.title).toBe('Nuxt')
expect(window.__NUXT__.beforeSerialize).toBe(true)
})

test('/error', async () => {
Expand Down
Expand Up @@ -7,7 +7,7 @@ export default {
middleware ({ beforeNuxtRender }) {
if (process.server) {
beforeNuxtRender(({ nuxtState }) => {
nuxtState.test = true
nuxtState.beforeNuxtRender = true
})
}
}
Expand Down
26 changes: 26 additions & 0 deletions test/fixtures/basic/pages/before-serialize.vue
@@ -0,0 +1,26 @@
<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.beforeSerialize((nuxtState) => {
nuxtState.beforeSerialize = true
})
}
},
beforeMount () {
this.nuxtState = window.__NUXT__
}
}
</script>

0 comments on commit 9f02e5d

Please sign in to comment.