User defined rewrites are "normalized" so that our internal rewrites are still properly handled. Before normalizing these rewrites, the Next.js builder will attempt to match server action requests to a`.action` variant. Then the user-defined rewrites flow through the afterFiles normalization ([this part](https://github.com/vercel/vercel/blob/fix/unmatched-action-rewrites/packages/next/src/server-build.ts#L254-L279)) so that when we add `.action` in the builder, we don't drop the suffix.
But this normalization can lead to a malformed `dest`. e.g., if I had rewrite like this:
```js
{
source: '/greedy-rewrite/static/:path*',
destination: '/static/:path*',
}
```
The builder would go through this flow on an action request to `/greedy-rewrite/static`:
1. It'll attempt to match it to a `.action` output, so `/greedy-rewrite/static` -> `/greedy-rewrite/static.action`
2. The afterFiles normalization will take place, so the original `dest` of `/static/$1` will become `/static/$1$rscsuff`
3. $1 will be an empty string, because it doesn't match the existing capture group. So now `/greedy-rewrite/static.action` -> `/greedy-rewrite/static/.action`
4. `static/.action` is not a valid output, so it'll 404 and the action will break.
Existing handling exists for `.rsc` outputs for a similar reason, but only on the index route. I added a similar fix for this in #11688.
When deploying partial prerendering (PPR), there may some pages that are
not enabled for PPR but still appear in the `prerender-manifest.json`.
Due to the branching of the client router, these routes also have to
have a `.rsc` as well as a `.prefetch.rsc` variants in order to prevent
404's. This change adds support for adding the extra route to the
prerender for pages that have PPR disabled.
The builder normalizes user rewrites that target pages that have special outputs (`.rsc`, `.prefetch.rsc`). When we added support for `.action` outputs, we need to perform this same normalization to ensure that user rewrites still match. If the rewrite was a greedy match (eg `/:path*`) it'd be ok, but more specific rewrites would have the issue.
When PPR is enabled in incremental mode, the previous code used the page information to determine if there was a failure for generating the flight data. This has been moved to the app PPR setting instead.
When specifying a functions configuration in `vercel.json`, we attempt to find source files for all entrypoints. This attempts to normalize those source paths for some special cases so that we don't show a build warning for completely normal usage.
- `/_not-found` is an entrypoint automatically inserted by Next.js -- if we don't find a source file for it, don't warn, as the user might not have added one
- special metadata files like `favicon.ico` and `opengraph-image.<ext>` will be bundled as `favicon.ico/route.js` but the source file will be the raw extension.
When rewriting requests that contain a `next-action` header to a `.action` output, we should do so only in the case where the RSC header isn't present. When a Next.js server action triggers a `redirect`, an intra-app RSC request will be made to that requested URL, with the `next-action` header still present. This means the intra-app request will be incorrectly rewritten, when we only intended to handle the actual action request.
This was patched in Next.js in the following PR:
- https://github.com/vercel/next.js/pull/65615
But it seems like a good idea to be resilient to this here as well.
Since we're rewriting `next-action` requests to `.action` outputs, we need to ensure that we also duplicate the edge function handler for it.
This runs all of the existing Node runtime tests in the Edge runtime as well. However, there's a discrepancy in how `x-vercel-cache` is returned, so for now we instead validate that its responding with `x-edge-runtime`.
This fixes the logic that detects if partial prerendering (PPR) has been
enabled for a project. The new incremental adoption pathway allows
setting the `experimental.ppr = 'incremental'` which the previous code
did not support.
This ensures we properly name the outputs when a basePath is present for the `index` output as previously we weren't properly routing to the RSC output due to nested `index` naming/route conflict. This only was a noticeable issue with prerender/static index outputs with base path and app router since if the index route was dynamic it would still catch the RSC request and just handle it without the correct naming.
Fixes: https://github.com/vercel/next.js/issues/64903
This ensures we properly create `.prefetch.rsc` output aliases for non-prerender outputs when PPR is enabled so that we can properly route which handles the interception route case as that is always dynamic so was missing it's `.prefetch.rsc` output causing the prefetch request to 404 unexpectedly.
x-ref: [slack thread](https://vercel.slack.com/archives/C070ZMMKVU7/p1714511126337289)
When generating the outputs for pages when app router is also present we weren't creating the placeholder `.rsc` outputs for all prerender outputs so when a `fallback: false` route was configured in the pages router that could fall through to an app route it causes issues with client-navigation behaving differently than a direct visit.
This ensures we add the placeholder `.rsc` outputs for all prerenders so that `fallback: false` pages don't have this unexpected behavior.
This only rewrites requests that contain a `next-action` header (explicitly indicating it's a server action). A side effect is that POST requests to a server action on a static route, without a next-action header, won't be marked as streaming (but will still execute normally). This is fine as only the handled action needs to stream.
This relands .action handling behind a feature flag.
There aren't currently any tests for server actions which have special handling in the builder. This adds tests to help avoid regressions in future Next.js builder work.
Invoking an action that's a Prerender will currently bypass the static cache (via `experimentalBypassFor`), but the prerender group doesn't support streaming.
This clones the prerender group and adds corresponding rewrites for those requests. Separately, we'll deprecate `experimentalBypassFor`.
Depends on:
- https://github.com/vercel/next.js/pull/64592
In the past, we used the `VERCEL_ANALYTICS_ID` environment variable with the previous Speed Insights feature on Vercel to activate specific logic in Next.js, Nuxt and Gatsby for collecting and sending web vitals data.
With the new Speed Insights, that's not required anymore.
We no longer want to set the environment variable when detecting the new `@vercel/speed-insights` package.
This PR confirms that the variable is not set if the new package is detected.
This ensures we properly include `_not-found` assets when present for
app router specific functions as otherwise when attempting to render
`notFound()` case we can hit `MODULE_NOT_FOUND` errors. A test case for
this behavior has been added under `00-app-router-not-found`.
Closes: [NEXT-3084](https://linear.app/vercel/issue/NEXT-3084)
Historically, we used to have a compressed function size limit of `50MB` but this is a very old limit and was removed long ago. Considering this limit is removed and it requires additional overhead to calculate, this removes the compressed size limit handling while leaving the uncompressed size limit detection/handling.
When there's a match for a prerender, the dynamic query parameters will
not be provided via the `x-now-route-matches`. This ensures that when
generating any static route that the static streaming lambda path is
used if it's provided, ensuring that when a page is generated via
`generateStaticParams`:
```tsx
// app/blog/[slug]/page.tsx
type Props = {
params: {
slug: string
}
}
export function generateStaticParams() {
return [{ slug: "one" }, { slug: "two" }, { slug: "three" }]
}
export default function BlogPage({ slug }: Props) {
// ...
}
```
That we use the specific routes (`/blog/one`, `/blog/two`, and
`/blog/three`) for the partial prerendering streaming path instead of
the paramatarized pathname (`/blog/[slug]`) as the rewrites won't be
matched once a match for a prerender has been found.
This additionally updates the tests to ensure that the correct pathname
is observed (this was previously silently failing).
The Next.js change in https://github.com/vercel/next.js/pull/61794 means
that the `Vary` header will contain `Next-Url` less often. We need to
update the assertions on our end to accommodate.
This ensures we add handling for our internal `.rsc` suffixes for rewrites since this currently fail to match by default unless the user manually adds handling for this. Updated our test fixture to ensure this is tested properly.
It seems the intention of this test was to verify that the rewritten
file matches the original file, but it does so by just asserting on
arbitrary script text, which is brittle and broke as a result of
https://github.com/vercel/next.js/pull/56294
The right way to test this would be to fetch the original script and
compare the contents with the rewritten script, but this relies on
`__NEXT_SCRIPT__` magic which is only available in probe checks. For now
this just asserts on a valid status code, as a chunk that isn't properly
rewritten should 404 in this case.
`getSourceFilePathFromPage` attempts to match patterns found in `vercel.json` with source files. However, the `page` argument to this function is stripped of route groups, so these files are erroneously skipped and function settings are not applied.
For app-dir routes which might contain route groups, this checks an internal mapping which maps the "normalized" paths (e.g. `app/dashboard/[slug]/page.js`) to the file-system path (e.g. `app/dashboard/[slug]/(group)/page.js`)
This adds some tests to the PPR implementation for Next.js. This also
fixes a bug where the static pages were incorrectly generating a header
that falsly indicated that it postponed.
This adds a new `getRequestHandlerWithMetadata` export if enabled and
available to the exported method.
---------
Co-authored-by: Joe Haddad <timer@vercel.com>
Co-authored-by: JJ Kasper <jj@jjsweb.site>
When using `basePath` with statically generated routes, the builder
currently generates lambdas for the root route that conflict with the
prerender functions generated.
E.g. if we have `basePath: "test"` and a root route at: `app/page.js`,
this is currently the output:
```
test
test.rsc
test/index
test/index.rsc
```
The result is that visiting the deployed app at `/test` renders an
incomplete page. On the other hand visiting `/test/index` outputs the
expected markup.
It seems like the intent is that we want to delete the lambdas that
conflict with the prerender functions. I've updated the lambda name
generation logic when doing the deleting to line up with how the lambda
names are generated initially.
Follow-up to https://github.com/vercel/vercel/pull/10750 this removes the underscore prefetching from all prefetch outputs and instead only applies it to the index route itself as this causes issues with PPR making these outputs prerenders and being able to interpolate the route param values.
There is the edge case of a user returning the literal value `index` from `generateStaticParams` but we can tolerate that more than ppr not working as expected.
Follow-up to https://github.com/vercel/vercel/pull/10734 -- but considers that the static prefetch associated with `/` might be inside of a dir such as `index/index.prefetch.rsc`.
To avoid any future matching conflicts, this PR updates to prefix all static prefetches
`next export` has been deprecated on the latest Next.js canary so these
tests will no longer pass.
This changes it to use `output: export` from `next.config.js` instead.
---------
Co-authored-by: JJ Kasper <jj@jjsweb.site>
This reverts commit e9026c7a69.
This was causing some builds using Turbo + Next.js to fail with:
```
...writing to cache...
--
17:02:42.820 | Traced Next.js server files in: 169.874ms
17:02:42.871 | Error: Config file was not found at "/vercel/output/config.json"
17:02:42.871 | at f3 (/var/task/sandbox.js:239:2647)
17:02:42.872 | at async TCe (/var/task/sandbox.js:245:4681)
17:02:42.872 | at async WBt (/var/task/sandbox.js:261:1990)
17:02:42.872 | at async zBt (/var/task/sandbox.js:261:1791)
```
INC-442