Skip to content

Proposed Changes to use the Vercel Build Output for Routing #129

Closed
@james-elicx

Description

@james-elicx

Hello, this issue outlines the proposed changes that I would like to make to how next-on-pages handles routing.

The Vercel build output config contains the different steps taken during the routing process used by Vercel, in a logical format, and was designed around making it easy for frameworks to build and deploy on Vercel. This is advantageous in that we can attempt to mirror how their routing works by using this config.

I previously intended to create a PR once I had a working concept, although I feel it would be more beneficial for me to create an issue outlining how I intend it to function. This is so that these thoughts can be discussed and prevent me from wasting time implementing a section that people may disagree on.

I imagine parts of the proposed system may seem confusing at first glance. I am happy to answer any questions you may have about how I have laid it out.

I would appreciate it if this issue could be assigned to me as I would like to build it out :)

Current System

Build time

We extract the middleware manifest from the Next.js build and use this to find our function files. We then minify the entry points and inject the middleware manifest matches and the entry point into the worker script. Additionally, we inject the Vercel build output config.

Runtime

Upon each request, we currently loop through the Vercel build output config, check requirements such as method/has/missing/caseSensitive, and then check if the src value matches. If it does, we add the route to a list of matching routes. If there was no src value at all, we also add that handle to the matching routes list. After all that, we check for middleware matches in that list of matching routes and run any middleware. We then loop through all the injected functions and check for a match there. If one is found, we return the value of calling the entry point.

Proposed System

These changes remove the need to use the Next.js build output's middleware manifest and rely solely on the Vercel build output. The routing process during runtime is based on the routing handler phases from the Vercel build output config.

Through analysing the result of building with various rewrite options and consulting the Next.js documentation, I further established that dynamic routes and non-dynamic routes are handled at two different points. Additionally, it became clear that dynamic params are handled in the rewrite phase during runtime through two separate regular expressions that add the params as search params. With respect to middleware, the documentation also detailed that they run between redirects and the first rewrite options.

All the phases listed under runtime are in the order that they occur in the build output's config, except for the resource phase. In the outputted config, the resource phase is written between filesystem and miss. I do not believe it should be run at this point based on what I have read, and the below list reflects the points at which each phase will logically run, mostly matching up with the Vercel config. The reason for this is that the resource phase handles the fallback rewrite option. Per the Next.js docs, this rewrite option is applied after all routes+static assets are checked, thus leading me to put it where I believe it would logically take place.

Tests should of course be added when any implementations of the new system are written.

Build time

Inject the build output config (.vercel/output/config.json) into the worker script.

Static assets (.vercel/output/static):

  • Extract the path names.
  • Add the path names to a map of path names to path info.

Functions (.vercel/output/functions):

  • Extract the path names.
  • Extract the entry points.
  • Minify the entry points.
  • Add the path names to a map of path names to path info (with minfied entry point).

Inject the map of path names to path data/info into the worker script.

Runtime

no handler phase

  • applies headers.
  • applies redirects.
  • applies/processes middleware.
  • applies beforeFiles rewrites.
  • continue === false -> return response.

filesystem phase (occurs if path name not found in functions list (non-dynamic) or static paths)

  • applies afterFiles rewrites.
  • check === true -> check filesystem phase again after the rewrite phase.

miss phase (occurs if filesystem phase misses - no src match)

  • check === true -> check filesystem phase again after the rewrite phase.

rewrite phase (occurs always)

  • applies dynamic params.
  • check pathname is in functions (incl. dynamic) or static paths.
    • miss ->
      • if check === true earlier:
        • enter filesystem phase.
          • no src match -> enter miss phase.
      • else:
        • enter resource phase.

resource phase (occurs if rewrite phase ultimately resulted in filesystem miss)

  • applies fallback rewrites.
  • check === true
    • enter filesystem phase.
      • no src match -> final result is miss.

hit phase (occurs if a function file path or static path matched)

  • call the function's entrypoint.
  • return response with applied headers + status code.

error phase (occurs if response code was 4xx or 5xx)

  • if status matches, rewrite to dest.
  • return response.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions