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

fix(vue-app): preview mode fetch #10489

Merged
merged 6 commits into from Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 16 additions & 9 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 promises = pages.map(async (page) => {
const 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,20 @@ export default {
)
}
<% } %>

<% if (features.fetch) { %>
// Wait for asyncData & old fetch to finish
await Promise.all(p)
pi0 marked this conversation as resolved.
Show resolved Hide resolved

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()
}
}