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

next.js server router no longer exposed in 10.0.8+ #23558

Closed
lineape opened this issue Mar 30, 2021 · 5 comments
Closed

next.js server router no longer exposed in 10.0.8+ #23558

lineape opened this issue Mar 30, 2021 · 5 comments
Labels
bug Issue was opened via the bug report template.

Comments

@lineape
Copy link

lineape commented Mar 30, 2021

What version of Next.js are you using?

10.0.8, 10.0.9, 10.1.x

What version of Node.js are you using?

14

What browser are you using?

chrome

What operating system are you using?

macOS

How are you deploying your application?

AWS

Describe the Bug

In next.js 10.0.8+, the return value of calling the next custom server function (i.e. const app = next({})) no longer has a router field.

This router was exposed in previous versions and was not marked as internal or deprecated.

(Note the 'old' server with the router is still accessible via the .server field, but that is marked as a private field in the new NextServer class)

Expected Behavior

Accessing the router is possible

To Reproduce

install next 10.0.8, 10.0.9, or 10.1.x

  const next = require('next');
  const app = next({});

  app.router.pageChecker('/hello').then(console.log); // logs true or false in 10.0.7, but throws Uncaught TypeError: Cannot read property 'pageChecker' of undefined in new versions
@lineape lineape added the bug Issue was opened via the bug report template. label Mar 30, 2021
@lineape lineape changed the title next.js server router no longer exposed in 10.1 next.js server router no longer exposed in 10.0.8+ Mar 30, 2021
@lineape
Copy link
Author

lineape commented Mar 30, 2021

The change happened in commit 1ebc9bb in packages/next/server/next.ts when the return type of createServer was changed from Server to the newly introduced NextServer class

Would it be possible to make the getServer method in NextServer public so that we can access the underlying Server instance (and the router)?

@timneutkens
Copy link
Member

timneutkens commented Mar 31, 2021

app.router has never been a public method for use in any application. Please make sure you only use methods that are documented in the documentation as backwards compat can't be guaranteed when your application is using Next.js internals.

I've opened a PR to update the automatically generated typing: #23573

timneutkens added a commit to timneutkens/next.js that referenced this issue Mar 31, 2021
Seems that some people (vercel#23558) are using Next.js internals based on the typings that TS generates automatically even though these values are not documented / should not be used in applications. This ensures the router value on Server is not used by accident.
ijjk added a commit that referenced this issue Mar 31, 2021
* Mark this.router protected

Seems that some people (#23558) are using Next.js internals based on the typings that TS generates automatically even though these values are not documented / should not be used in applications. This ensures the router value on Server is not used by accident.

* Mark all variables as protected

#23349

* fix type error

Co-authored-by: JJ Kasper <jj@jjsweb.site>
@KODerFunk
Copy link

@timneutkens No information in docs about checking routes in custom servers.
I use custom server for multilayer caching (api-cache + ssr-cache), and need to predict request type (page | resource) for pre-SSR handling, for make routine around user-agent and cookie/session (we progressive split large legacy Rails+custom_ssr+React monolith/hybrid).
It is very important. Many people fight with this and other features (https://stackoverflow.com/questions/59749983/how-to-check-if-a-page-exist-in-a-custom-server-using-next-js).

Now I have to make ugly crutches in the code and track the changes in the Next.js code 😞

SokratisVidros pushed a commit to SokratisVidros/next.js that referenced this issue Apr 20, 2021
* Mark this.router protected

Seems that some people (vercel#23558) are using Next.js internals based on the typings that TS generates automatically even though these values are not documented / should not be used in applications. This ensures the router value on Server is not used by accident.

* Mark all variables as protected

vercel#23349

* fix type error

Co-authored-by: JJ Kasper <jj@jjsweb.site>
@KODerFunk
Copy link

KODerFunk commented Apr 22, 2021

@timneutkens fyi, my crutches checkIsPagePath.ts:

import type { NextServer } from 'next/dist/server/next'
import type Server from 'next/dist/next-server/server/next-server'
import LRUCache from 'mnemonist/lru-cache'

const pageCheckingCacheSize = 1000
// Cache for `checkIsPagePath()` results with limit size (LRU) to avoid memory overflow attack.
// Cache-key is a "pathname", without query parameters.
const pageCheckingCache = new LRUCache<string, boolean>(pageCheckingCacheSize)

/**
 * Ugly crutches for detection of page request,
 * coherent with Next.js undocumented protected mechanics.
 * !!! Be careful when update Next.js !!!
 * @see https://github.com/vercel/next.js/issues/23558#issuecomment-820655560
 * @param app - Accessible next-server.
 * @param path - Request path.
 * @returns Promise with answer to question "Is this SSR page path?"
 */
export default async function checkIsSSRPath(app: NextServer, path: string): Promise<boolean> {
  // https://nodejs.org/api/url.html#url_url_strings_and_url_objects
  const searchPosition = path.indexOf('?')
  const pathname = searchPosition > -1 ? path.slice(0, searchPosition) : path
  let result = pageCheckingCache.get(pathname)

  if (result === undefined) {
    result =
      // Fast cutoff static and SSP (SSP detected separately outside).
      !pathname.startsWith('/_next/')
      // @ts-expect-error Need access to protected router.
      && ((app.server as Server).router.dynamicRoutes.some(({ match }) => match(pathname))
        // @ts-expect-error Need access to protected router.
        || await (app.server as Server).router.pageChecker(pathname))

    pageCheckingCache.set(pathname, result)
  }

  return result
}

flybayer pushed a commit to blitz-js/next.js that referenced this issue Apr 29, 2021
* Mark this.router protected

Seems that some people (vercel#23558) are using Next.js internals based on the typings that TS generates automatically even though these values are not documented / should not be used in applications. This ensures the router value on Server is not used by accident.

* Mark all variables as protected

vercel#23349

* fix type error

Co-authored-by: JJ Kasper <jj@jjsweb.site>
@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

4 participants