Skip to content

Commit

Permalink
fix(vue-app): preview mode fetch (#10489)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdoesburg committed Jun 23, 2022
1 parent 7a25294 commit 123206c
Show file tree
Hide file tree
Showing 12 changed files with 323 additions and 11 deletions.
29 changes: 19 additions & 10 deletions packages/vue-app/template/App.js
Expand Up @@ -174,23 +174,16 @@ export default {
}
<% if (loading) { %>this.$loading.start()<% } %>
const promises = pages.map((page) => {
const p = []
const promises = pages.map(async (page) => {
let p = []
<% if (features.fetch) { %>
// Old fetch
if (page.$options.fetch && page.$options.fetch.length) {
p.push(promisify(page.$options.fetch, this.context))
}
if (page.$fetch) {
p.push(page.$fetch())
} else {
// Get all component instance to call $fetch
for (const component of getChildrenComponentInstancesUsingFetch(page.$vnode.componentInstance)) {
p.push(component.$fetch())
}
}
<% } %>
<% if (features.asyncData) { %>
if (page.$options.asyncData) {
p.push(
Expand All @@ -203,6 +196,22 @@ export default {
)
}
<% } %>
<% if (features.fetch) { %>
// Wait for asyncData & old fetch to finish
await Promise.all(p)
// Cleanup refs
p = []
if (page.$fetch) {
p.push(page.$fetch())
}
// Get all component instance to call $fetch
for (const component of getChildrenComponentInstancesUsingFetch(page.$vnode.componentInstance)) {
p.push(component.$fetch())
}
<% } %>
return Promise.all(p)
})
try {
Expand Down
1 change: 0 additions & 1 deletion packages/vue-app/template/utils.js
Expand Up @@ -58,7 +58,6 @@ export function getChildrenComponentInstancesUsingFetch(vm, instances = []) {
for (const child of children) {
if (child.$fetch) {
instances.push(child)
continue; // Don't get the children since it will reload the template
}
if (child.$children) {
getChildrenComponentInstancesUsingFetch(child, instances)
Expand Down
107 changes: 107 additions & 0 deletions test/dev/full-static-with-preview.test.js
@@ -0,0 +1,107 @@
import http from 'http'
import { resolve } from 'path'
import serveStatic from 'serve-static'
import finalhandler from 'finalhandler'
import { Builder, Generator, getPort, loadFixture, Nuxt, waitFor } from '../utils'

let port
const url = route => 'http://localhost:' + port + route
const rootDir = resolve(__dirname, '..', 'fixtures/full-static-with-preview')
const distDir = resolve(rootDir, '.nuxt-generate')

let builder
let server = null
let generator = null

describe('full-static-with-preview', () => {
beforeAll(async () => {
const config = await loadFixture('full-static-with-preview', {
generate: {
static: false,
dir: '.nuxt-generate'
}
})
const nuxt = new Nuxt(config)
await nuxt.ready()

builder = new Builder(nuxt)
builder.build = jest.fn()
generator = new Generator(nuxt, builder)

await generator.generate()

const serve = serveStatic(distDir)
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})

port = await getPort()
server.listen(port)
})

test('/', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called</p>')
})

test('preview: /', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/?preview=true'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called-in-preview</p>')
})

test('/with-component', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/with-component'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called</p>')
expect(html).toContain('<p>component-fetch-called</p>')
})

test('preview: /with-component', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/with-component?preview=true'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called-in-preview</p>')
expect(html).toContain('<p>component-fetch-called-in-preview</p>')
})

test('/with-nested-components', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/with-nested-components'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called</p>')
expect(html).toContain('<p>component-fetch-called</p>')
expect(html).toContain('<p>sub-component-fetch-called</p>')
})

test('preview: /with-nested-components', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/with-nested-components?preview=true'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called-in-preview</p>')
expect(html).toContain('<p>component-fetch-called-in-preview</p>')
expect(html).toContain('<p>sub-component-fetch-called-in-preview</p>')
})

test('/async-data-dependent-fetch', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/async-data-dependent-fetch'))
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called</p>')
expect(html).toContain('<p>component-1-fetch-called</p>')
expect(html).toContain('<p>component-2-fetch-called</p>')
expect(html).toContain('<p>component-3-fetch-called</p>')
})

test('preview: /async-data-dependent-fetch', async () => {
const window = await generator.nuxt.server.renderAndGetWindow(url('/async-data-dependent-fetch?preview=true'))
await waitFor(100)
const html = window.document.body.innerHTML
expect(html).toContain('<p>page-fetch-called-in-preview</p>')
expect(html).toContain('<p>component-1-fetch-called-in-preview</p>')
expect(html).toContain('<p>component-2-fetch-called-in-preview</p>')
expect(html).toContain('<p>component-3-fetch-called-in-preview</p>')
})

// Close server and ask nuxt to stop listening to file changes
afterAll(async () => {
await server.close()
})
})
@@ -0,0 +1,24 @@
<template>
<component :is="component.name" v-bind="component.props">
<template v-if="component.components">
<ComponentRenderer
v-for="nestedComponent in component.components"
:key="nestedComponent.id"
:component="nestedComponent"
/>
</template>
</component>
</template>

<script>
export default {
name: 'ComponentRenderer',
props: {
component: {
type: Object,
required: true
}
}
}
</script>
@@ -0,0 +1,29 @@
<template>
<div>
<p>{{ text }}</p>
<slot />
</div>
</template>

<script>
export default {
props: {
name: {
type: String,
default: 'component'
}
},
data () {
return {
text: ''
}
},
fetch () {
this.text = `${this.name}-fetch-called`
if (this.$preview) {
this.text = `${this.name}-fetch-called-in-preview`
}
}
}
</script>
@@ -0,0 +1,3 @@
import { buildFixture } from '../../utils/build'

buildFixture('full-static-with-preview')
7 changes: 7 additions & 0 deletions test/fixtures/full-static-with-preview/nuxt.config.js
@@ -0,0 +1,7 @@
export default {
target: 'static',
components: true,
plugins: [
'~/plugins/preview.client.js'
]
}
@@ -0,0 +1,59 @@
<template>
<div>
<p>{{ text }}</p>
<ComponentRenderer
v-for="component in components"
:key="component.id"
:component="component"
/>
</div>
</template>

<script>
const fetchData = () => {
return new Promise((resolve) => {
setTimeout(() => resolve([
{
id: 1,
name: 'ComponentWithFetch',
props: { name: 'component-1' },
components: [
{
id: 2,
name: 'ComponentWithFetch',
props: { name: 'component-2' },
components: []
},
{
id: 3,
name: 'ComponentWithFetch',
props: { name: 'component-3' },
components: []
}
]
}
]), 10)
})
}
export default {
name: 'Page',
async asyncData () {
const components = await fetchData()
return { components }
},
data () {
return {
text: ''
}
},
fetch () {
this.text = 'page-fetch-called'
if (this.$preview) {
this.text = 'page-fetch-called-in-preview'
}
}
}
</script>
22 changes: 22 additions & 0 deletions test/fixtures/full-static-with-preview/pages/index.vue
@@ -0,0 +1,22 @@
<template>
<div>
<p>{{ text }}</p>
</div>
</template>

<script>
export default {
data () {
return {
text: ''
}
},
fetch () {
this.text = 'page-fetch-called'
if (this.$preview) {
this.text = 'page-fetch-called-in-preview'
}
}
}
</script>
23 changes: 23 additions & 0 deletions test/fixtures/full-static-with-preview/pages/with-component.vue
@@ -0,0 +1,23 @@
<template>
<div>
<p>{{ text }}</p>
<ComponentWithFetch />
</div>
</template>

<script>
export default {
data () {
return {
text: ''
}
},
fetch () {
this.text = 'page-fetch-called'
if (this.$preview) {
this.text = 'page-fetch-called-in-preview'
}
}
}
</script>
@@ -0,0 +1,25 @@
<template>
<div>
<p>{{ text }}</p>
<ComponentWithFetch>
<ComponentWithFetch name="sub-component" />
</ComponentWithFetch>
</div>
</template>

<script>
export default {
data () {
return {
text: ''
}
},
fetch () {
this.text = 'page-fetch-called'
if (this.$preview) {
this.text = 'page-fetch-called-in-preview'
}
}
}
</script>
@@ -0,0 +1,5 @@
export default function ({ query, enablePreview }) {
if (query.preview) {
enablePreview()
}
}

0 comments on commit 123206c

Please sign in to comment.