Next.js: with-data-prefetch example doesn't work with Next v8

Created on 20 Feb 2019  路  11Comments  路  Source: vercel/next.js

Examples bug report

Example name

with-data-prefetch

Describe the bug

The example fails to compile with this error:

This dependency was not found:

* next/dist/lib/utils in ./components/link.js

To install it, you can run: npm install --save next/dist/lib/utils

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Install the example npx create-next-app --example with-data-prefetch with-data-prefetch-app
  2. Install the deps npm install
  3. Run the example npm run dev
  4. See error

Expected behavior

The example should run and data prefetching should work as described.

Screenshots

System information

  • OS: macOS
  • Version of Next.js: latest

Additional context

This bug also affects the data-prefetch-link library and the next-apollo library.

good first issue

Most helpful comment

Hey @timneutkens 馃憢 - what are the internal APIs that this example currently relies on that we can expose to make prefetching data possible again?

All 11 comments

Please send a PR fixing. 馃槃

In addition to the missing module issue reported above, looks like maybe some architecture changed here.

This line now returns undefined and it used to return a component.

prefetch used to return this.pageLoader.loadpage by way of fetchRoute.

Now, it checks if hasPreload and if it does, it loads the script and returns.

Yeah I was telling @Timer this example can't be fixed without core changes. We might allow an option passed to router.prefetch however it's a dangerous to use data prefetching already, as it doesn't happen in the background.

@timneutkens gotcha. Are you implying that data prefetching is no longer possible with nextjs?

I'm saying that this solution/example is using internal APIs hence why it breaks on majors. We should probably expose an external API for loading the component.

We should probably expose an external API for loading the component.

^^ That would be pretty awesome!

Hey @timneutkens 馃憢 - what are the internal APIs that this example currently relies on that we can expose to make prefetching data possible again?

Given that the example no longer works in Next 8, will you be happy to accept a PR that deletes it from canary? I spent a couple of hours setting up something similar in my app before realising that await router.prefetch(parsedHref) is now undefined instead of being a component.

There's a method called fetchComponent in Router class:

https://github.com/zeit/next.js/blob/564eac47462cf65cd80c140dff72160845e4e4de/packages/next-server/lib/router/router.ts#L528-L549

For some reason fetchComponent isn't mentioned in RouterProps TypeScript type definition:

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/3fee2364dfda7c2beb65dc6e1980e41b2ed30751/types/next-server/router.d.ts#L32-L73

If you use TypeScript, it is possible to still call/reference the method by casting RouterProps to something that contains the fetchComponent method.

My following approach isn't perfect but at least it fetched the component, hence able to call the getInitialProps:

import Router from 'next/router'
import { UrlLike, RouterProps } from 'next-server/router'
import { format, resolve, parse } from 'url'

interface MyRouterProps extends RouterProps {
  fetchComponent: (route: string) => Promise<NextComponentType>
}

type UrlAlike = string | UrlLike

export default async (href: UrlAlike, asPath?: UrlAlike) => {
  if (typeof window === 'undefined') return

  const hrefString = href === 'string' ? href : format(href)
  const route = resolve(location.pathname, hrefString)

  if (Router.router === null) return

  // the following fetches the component for the valid route
  const component = await (router as MyRouterProps).fetchComponent(route)
  // ...
}

edit: My approach avoids using Router.prefetch at all because its originating method seems to be written in a way it never returns anything:

https://github.com/zeit/next.js/blob/564eac47462cf65cd80c140dff72160845e4e4de/packages/next/client/page-loader.js#L166-L215

Replied on twitter but also posting here:

https://twitter.com/timneutkens/status/1145573026869760000

It鈥檚 a private method, hence why it鈥檚 not documented and not available in the types. I think I already replied there that we might want to expose a public method for it, however after that there was no community RFC to try and solve it.

Router.router is private too.

As said in my tweet I'd love for someone to draft up a RFC for this.

Requirements from my side:

  • Doesn't increase Router bundle size (maybe a separate function you import)
  • Only does prefetching work in the background / when idle (as it's quite heavy)

Closing as this example was deleted. Next.js automatically prefetches data when it's safe now (getStaticProps).

Was this page helpful?
0 / 5 - 0 ratings