framework icon indicating copy to clipboard operation
framework copied to clipboard

feat(nuxt3): support `prefetch` prop for `<nuxt-link>`

Open Mini-ghost opened this issue 3 years ago • 4 comments

🔗 Linked issue

#3649 #2086

❓ Type of change

  • [ ] 📖 Documentation (updates to the documentation or readme)
  • [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
  • [ ] 👌 Enhancement (improving an existing functionality like performance)
  • [x] ✨ New feature (a non-breaking change that adds functionality)
  • [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

Support prefetch prop for <nuxt-link>. This implementation is refer to https://github.com/nuxt/framework/discussions/2086#discussioncomment-1683819. Need a polyfill for requestIdleCallback ?

Also, I'm not sure how to use Link Prefetching like below, because path are unpredictable.

<link rel="prefetch" as="script" href="path" />

The implementation of this PR refers to nuxt2, maybe we can generate a router manifest. and mapping file path when triggering prefetch ?

📝 Checklist

  • [x] I have linked an issue or discussion.
  • [x] I have updated the documentation accordingly.

Mini-ghost avatar Apr 13 '22 14:04 Mini-ghost

Deploy Preview for nuxt3-docs canceled.

Name Link
Latest commit b7bea156255da5ae017570e939f9fd5552ec1fc9
Latest deploy log https://app.netlify.com/sites/nuxt3-docs/deploys/6320e387fc714e0008189c59

netlify[bot] avatar Apr 13 '22 14:04 netlify[bot]

Thank you for the PR @Mini-ghost 💚

From what I see, requestIdleCallback is not supported in Safari without a flag: https://caniuse.com/requestidlecallback

So I guess we need a polyfill for it, what would be the preferred approach to do so @pi0 ?

atinux avatar Apr 14 '22 13:04 atinux

@pi0 @Atinux I will add polyfill for requestIdleCallback. And I think we have two way to polyfill.

  1. import polyfill at topest of the file and run in client side.
const requestIdleCallback = process.client
  ? window.requestIdleCallback || function (cb) {
    const start = Date.now()
    const idleDeadline = {
      didTimeout: false,
      timeRemaining () {
        return Math.max(0, 50 - (Date.now() - start))
      }
    }
    return window.setTimeout(function () {
      cb(idleDeadline)
    }, 1)
  }
  : (() => {}) as any as Window['requestIdleCallback']
  1. When component mounted and need prefetch, implement with Singleton.
let requestIdleCallback: Window['requestIdleCallback'] | null = null
onMounted(() => {
  if (!shouldPrefetch.value) { return }

  // add `requestIdleCallback` polyfill if not supported and need prefetch
  if (!requestIdleCallback) {
    requestIdleCallback = window.requestIdleCallback || function (cb) {
      const start = Date.now()
      const idleDeadline = {
        didTimeout: false,
        timeRemaining () {
          return Math.max(0, 50 - (Date.now() - start))
        }
      }
      return window.setTimeout(function () {
        cb(idleDeadline)
      }, 1)
    }
  }
})

Which is the preferred approach?

Mini-ghost avatar Apr 16 '22 17:04 Mini-ghost

@Mini-ghost The first approach seems better to me 👍

danielroe avatar Jun 09 '22 15:06 danielroe

Thank you so much for helping on this feature @Mini-ghost <3

I've made few more reactors to the PR to simplify do small fixes and also integrated with new payload prerendering using link:prefetch hook to be ready to land.

pi0 avatar Sep 13 '22 20:09 pi0