mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-26 23:52:06 +00:00
feat(vue-app): add prefetch
prop to <nuxt-link>
(#6292)
This commit is contained in:
parent
ac5066c4e0
commit
7b3155347c
@ -17,7 +17,7 @@ import {
|
||||
globalHandleError
|
||||
} from './utils.js'
|
||||
import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js'
|
||||
import NuxtLink from './components/nuxt-link.<%= features.clientPrefetch && router.prefetchLinks ? "client" : "server" %>.js' // should be included after ./index.js
|
||||
import NuxtLink from './components/nuxt-link.<%= features.clientPrefetch ? "client" : "server" %>.js' // should be included after ./index.js
|
||||
<% if (isDev) { %>import consola from 'consola'<% } %>
|
||||
|
||||
<% if (isDev) { %>consola.wrapConsole()
|
||||
|
@ -29,6 +29,10 @@ export default {
|
||||
name: 'NuxtLink',
|
||||
extends: Vue.component('RouterLink'),
|
||||
props: {
|
||||
prefetch: {
|
||||
type: Boolean,
|
||||
default: <%= router.prefetchLinks ? 'true' : 'false' %>
|
||||
},
|
||||
noPrefetch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@ -39,7 +43,7 @@ export default {
|
||||
}<% } %>
|
||||
},
|
||||
mounted () {
|
||||
if (!this.noPrefetch) {
|
||||
if (this.prefetch && !this.noPrefetch) {
|
||||
this.handleId = requestIdleCallback(this.observe, { timeout: 2e3 })
|
||||
}
|
||||
},
|
||||
@ -59,7 +63,7 @@ export default {
|
||||
}
|
||||
// Add to observer
|
||||
if (this.shouldPrefetch()) {
|
||||
this.$el.__prefetch = this.prefetch.bind(this)
|
||||
this.$el.__prefetch = this.prefetchLink.bind(this)
|
||||
observer.observe(this.$el)
|
||||
this.__observed = true
|
||||
}<% if (router.linkPrefetchedClass) { %> else {
|
||||
@ -81,7 +85,7 @@ export default {
|
||||
|
||||
return Components.filter(Component => typeof Component === 'function' && !Component.options && !Component.__prefetched)
|
||||
},
|
||||
prefetch () {
|
||||
prefetchLink () {
|
||||
if (!this.canPrefetch()) {
|
||||
return
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ export default {
|
||||
name: 'NuxtLink',
|
||||
extends: Vue.component('RouterLink'),
|
||||
props: {
|
||||
prefetch: {
|
||||
type: Boolean,
|
||||
default: <%= router.prefetchLinks ? 'true' : 'false' %>
|
||||
},
|
||||
noPrefetch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
@ -32,7 +32,7 @@ export async function compileTemplate (template, destination, options = {}) {
|
||||
if (typeof template === 'string') {
|
||||
return {
|
||||
src: path.resolve(rootDir, '../template', template),
|
||||
dst: path.join(rootDir, '.nuxt', path.basename(template)),
|
||||
dst: path.join(rootDir, '.nuxt', destination || path.basename(template)),
|
||||
custom: false
|
||||
}
|
||||
}
|
||||
|
163
packages/vue-app/test/nuxt-link.client.prefetch.test.js
Normal file
163
packages/vue-app/test/nuxt-link.client.prefetch.test.js
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import { mount, RouterLinkStub } from '@vue/test-utils'
|
||||
import { vmTick, compileTemplate, importComponent } from './__utils__'
|
||||
|
||||
/* eslint-disable no-console */
|
||||
describe('nuxt-link prefetch', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers()
|
||||
|
||||
jest.spyOn(console, 'warn')
|
||||
jest.spyOn(console, 'error')
|
||||
})
|
||||
|
||||
afterAll(() => jest.restoreAllMocks())
|
||||
|
||||
test('when router.prefetchLinks is set to false, link with no prop should not be prefetched',
|
||||
async () => {
|
||||
const compiledTemplatePath = await compileTemplate(
|
||||
'components/nuxt-link.client.js',
|
||||
'nuxt-link.client.prefetch.0.js',
|
||||
{ router: { prefetchLinks: false } }
|
||||
)
|
||||
|
||||
const Component = await importComponent(compiledTemplatePath)
|
||||
Component.extends = RouterLinkStub
|
||||
|
||||
const methods = { observe: jest.fn() }
|
||||
|
||||
const wrapper = mount(Component, {
|
||||
propsData: { to: '/link' },
|
||||
methods
|
||||
})
|
||||
|
||||
jest.runAllTimers()
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
|
||||
expect(wrapper.props('prefetch')).toBe(false)
|
||||
expect(wrapper.props('noPrefetch')).toBe(false)
|
||||
expect(methods.observe).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('when router.prefetchLinks is set to false, link with prefetch prop set to true should be prefetched',
|
||||
async () => {
|
||||
const compiledTemplatePath = await compileTemplate(
|
||||
'components/nuxt-link.client.js',
|
||||
'nuxt-link.client.prefetch.1.js',
|
||||
{ router: { prefetchLinks: false } }
|
||||
)
|
||||
|
||||
const Component = await importComponent(compiledTemplatePath)
|
||||
Component.extends = RouterLinkStub
|
||||
|
||||
const methods = { observe: jest.fn() }
|
||||
|
||||
const wrapper = mount(Component, {
|
||||
propsData: { to: '/link', prefetch: true },
|
||||
methods
|
||||
})
|
||||
|
||||
jest.runAllTimers()
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
|
||||
expect(wrapper.props('prefetch')).toBe(true)
|
||||
expect(wrapper.props('noPrefetch')).toBe(false)
|
||||
expect(methods.observe).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('when router.prefetchLinks is set to true (default), link with no prop should be prefetched',
|
||||
async () => {
|
||||
const compiledTemplatePath = await compileTemplate(
|
||||
'components/nuxt-link.client.js',
|
||||
'nuxt-link.client.prefetch.2.js',
|
||||
{}
|
||||
)
|
||||
|
||||
const Component = await importComponent(compiledTemplatePath)
|
||||
Component.extends = RouterLinkStub
|
||||
|
||||
const methods = { observe: jest.fn() }
|
||||
|
||||
const wrapper = mount(Component, {
|
||||
propsData: { to: '/link' },
|
||||
methods
|
||||
})
|
||||
|
||||
jest.runAllTimers()
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
|
||||
expect(wrapper.props('prefetch')).toBe(true)
|
||||
expect(wrapper.props('noPrefetch')).toBe(false)
|
||||
expect(methods.observe).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('when router.prefetchLinks is set to true (default), link with prefetch prop set to false should not be prefetched',
|
||||
async () => {
|
||||
const compiledTemplatePath = await compileTemplate(
|
||||
'components/nuxt-link.client.js',
|
||||
'nuxt-link.client.prefetch.3.js',
|
||||
{}
|
||||
)
|
||||
|
||||
const Component = await importComponent(compiledTemplatePath)
|
||||
Component.extends = RouterLinkStub
|
||||
|
||||
const methods = { observe: jest.fn() }
|
||||
|
||||
const wrapper = mount(Component, {
|
||||
propsData: { to: '/link', prefetch: false },
|
||||
methods
|
||||
})
|
||||
|
||||
jest.runAllTimers()
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
|
||||
expect(wrapper.props('prefetch')).toBe(false)
|
||||
expect(wrapper.props('noPrefetch')).toBe(false)
|
||||
expect(methods.observe).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('when router.prefetchLinks is set to true (default), link with noPrefetch prop should not be prefetched',
|
||||
async () => {
|
||||
const compiledTemplatePath = await compileTemplate(
|
||||
'components/nuxt-link.client.js',
|
||||
'nuxt-link.client.prefetch.4.js',
|
||||
{}
|
||||
)
|
||||
|
||||
const Component = await importComponent(compiledTemplatePath)
|
||||
Component.extends = RouterLinkStub
|
||||
|
||||
const methods = { observe: jest.fn() }
|
||||
|
||||
const wrapper = mount(Component, {
|
||||
propsData: { to: '/link', noPrefetch: true },
|
||||
methods
|
||||
})
|
||||
|
||||
jest.runAllTimers()
|
||||
await vmTick(wrapper.vm)
|
||||
|
||||
expect(console.warn).not.toHaveBeenCalled()
|
||||
expect(console.error).not.toHaveBeenCalled()
|
||||
|
||||
expect(wrapper.props('prefetch')).toBe(true)
|
||||
expect(wrapper.props('noPrefetch')).toBe(true)
|
||||
expect(methods.observe).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
/* eslint-enable no-console */
|
@ -5,6 +5,10 @@
|
||||
"to": {
|
||||
"description": "Denotes the target route of the link. When clicked, the value of the to prop will be passed to router.push() internally, so the value can be either a string or a location descriptor object."
|
||||
},
|
||||
"prefetch": {
|
||||
"type": "boolean",
|
||||
"description": "Prefetch route target (overrides router.prefetchLinks value in nuxt.config.js)."
|
||||
},
|
||||
"no-prefetch": {
|
||||
"description": "Avoid prefetching route target."
|
||||
},
|
||||
|
@ -21,6 +21,7 @@
|
||||
"exact",
|
||||
"event",
|
||||
"exact-active-class",
|
||||
"prefetch",
|
||||
"no-prefetch"
|
||||
],
|
||||
"description": "Component for navigating between Nuxt pages."
|
||||
@ -35,6 +36,7 @@
|
||||
"exact",
|
||||
"event",
|
||||
"exact-active-class",
|
||||
"prefetch",
|
||||
"no-prefetch"
|
||||
],
|
||||
"description": "Component for navigating between Nuxt pages."
|
||||
|
Loading…
Reference in New Issue
Block a user